xilisf: Created new minor version.
This patch deprecates the xilisf_v5_2 and created new minor version xilisf_v5_3. Signed-off-by: P L Sai Krishna <lakshmis@xilinx.com>
This commit is contained in:
parent
159e188d9d
commit
dbff6b1fe4
31 changed files with 19632 additions and 0 deletions
58
lib/sw_services/xilisf/data/xilisf.mld
Executable file
58
lib/sw_services/xilisf/data/xilisf.mld
Executable file
|
@ -0,0 +1,58 @@
|
|||
###############################################################################
|
||||
#
|
||||
# Copyright (C) 2012 - 2015 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
|
||||
# XILINX 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
|
||||
# ----- ---- -------- -----------------------------------------------
|
||||
# 2.04a sdm 08/01/11 Added new parameter for Numonyx quad flash devices.
|
||||
# 3.00a srt 06/20/12 Updated to support interfaces SPI PS and QSPI PS.
|
||||
# Added support to SST flash.
|
||||
# 3.00a srt 02/06/13 Changed the serial flash family options to include
|
||||
# Spansion flash (CR 696379).
|
||||
# 5.1 sb 12/23/14 Added Micron to the serial flash family options.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
OPTION psf_version = 2.1;
|
||||
|
||||
BEGIN LIBRARY xilisf
|
||||
OPTION drc = isf_drc;
|
||||
OPTION copyfiles = all;
|
||||
OPTION REQUIRES_OS = (standalone xilkernel);
|
||||
OPTION APP_LINKER_FLAGS = "-Wl,--start-group,-lxilisf,-lxil,-lgcc,-lc,--end-group";
|
||||
OPTION desc = "Xilinx In-system and Serial Flash Library";
|
||||
OPTION VERSION = 5.3;
|
||||
OPTION NAME = xilisf;
|
||||
PARAM name = serial_flash_family, desc = "Indicates the Serial Flash family type. Enter 1 for ATMEL. 2 for INTEL. 3 for STM (M25PXX). 4 for Winbond. 5 for Spansion / Micron. 6 for SST Flash", type = int, default = 1;
|
||||
PARAM name = serial_flash_interface, desc = "Indicates the Serial Flash Interface. Enter 1 for AXI SPI. 2 for PS SPI. 3 for PS QSPI.", type = int, default = 1;
|
||||
END LIBRARY
|
191
lib/sw_services/xilisf/data/xilisf.tcl
Executable file
191
lib/sw_services/xilisf/data/xilisf.tcl
Executable file
|
@ -0,0 +1,191 @@
|
|||
###############################################################################
|
||||
#
|
||||
# Copyright (C) 2012 - 2015 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
|
||||
# XILINX 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
|
||||
# ----- ---- -------- -----------------------------------------------
|
||||
# 2.01a sdm 06/17/10 Updated to support axi_spi
|
||||
# 2.02a sdm 09/24/10 updated to use Tcl commands instead of unix commands
|
||||
# 2.03a sdm 04/17/11 Updated to support axi_quad_spi
|
||||
# 2.04a sdm 08/01/11 Added new parameter for Numonyx quad flash devices.
|
||||
# 3.00a srt 06/20/12 Updated to support interfaces SPI PS and QSPI PS.
|
||||
# Added support to SST flash.
|
||||
# 3.02a srt 05/13/13 Removed compiler errors when not selecting proper
|
||||
# interface for Zynq. (CR 716451)
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
#---------------------------------------------
|
||||
# ISF_drc - check system configuration and make sure
|
||||
# all components to run ISF are available.
|
||||
#---------------------------------------------
|
||||
|
||||
proc isf_drc {libhandle} {
|
||||
puts "Running DRC for XilIsf library... \n"
|
||||
|
||||
# find the list of xps or opb spi cores
|
||||
set sw_processor [hsi::get_sw_processor]
|
||||
set processor [hsi::get_cells [common::get_property HW_INSTANCE $sw_processor]]
|
||||
|
||||
set spi_periphs_list [get_spi_periphs $processor]
|
||||
|
||||
if { [llength $spi_periphs_list] == 0 } {
|
||||
set cpuname [common::get_property NAME $processor]
|
||||
error "ERROR: No SPI core is addressable from processor $cpuname. \
|
||||
XilIsf library requires a SPI Core \n"
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
proc get_spi_periphs {processor} {
|
||||
set periphs_list [::hsi::utils::get_proc_slave_periphs $processor]
|
||||
set spi_periphs_list {}
|
||||
|
||||
global spi_periphs_name_list
|
||||
set spi_periphs_name_list {}
|
||||
|
||||
foreach periph $periphs_list {
|
||||
set periphname [common::get_property IP_NAME $periph]
|
||||
if {$periphname == "xps_spi"
|
||||
|| $periphname == "opb_spi"
|
||||
|| $periphname == "xps_insystem_flash"
|
||||
|| $periphname == "axi_spi"
|
||||
|| $periphname == "axi_quad_spi"
|
||||
|| $periphname == "ps7_spi"
|
||||
|| $periphname == "ps7_qspi"} {
|
||||
lappend spi_periphs_list $periph
|
||||
lappend spi_periphs_name_list $periphname
|
||||
}
|
||||
}
|
||||
|
||||
return $spi_periphs_list
|
||||
}
|
||||
|
||||
#--------
|
||||
# Check the following h/w requirements for XilIsf:
|
||||
#--------
|
||||
proc isf_hw_drc {libhandle spi_list} {
|
||||
}
|
||||
|
||||
|
||||
# SPI hw requirements
|
||||
proc isf_spi_hw_drc {libhandle spi} {
|
||||
|
||||
}
|
||||
|
||||
|
||||
proc generate {libhandle} {
|
||||
|
||||
}
|
||||
|
||||
|
||||
#-------
|
||||
# post_generate: called after generate called on all libraries
|
||||
#-------
|
||||
proc post_generate {libhandle} {
|
||||
xgen_opts_file $libhandle
|
||||
|
||||
}
|
||||
|
||||
#-------
|
||||
# execs_generate: called after BSP's, libraries and drivers have been compiled
|
||||
# This procedure builds the libisf.a library
|
||||
#-------
|
||||
proc execs_generate {libhandle} {
|
||||
|
||||
}
|
||||
|
||||
|
||||
proc xgen_opts_file {libhandle} {
|
||||
|
||||
# Open xparameters.h file
|
||||
set file_handle [::hsi::utils::open_include_file "xparameters.h"]
|
||||
|
||||
# -----------------------------
|
||||
# Generate Flash options
|
||||
# -----------------------------
|
||||
puts $file_handle "/* Xilinx EDK In-system and Serial Flash Library (XilIsf) User Settings */"
|
||||
set serial_flash_family [common::get_property CONFIG.serial_flash_family $libhandle]
|
||||
puts $file_handle "\#define XPAR_XISF_FLASH_FAMILY $serial_flash_family"
|
||||
|
||||
set serial_flash_interface [common::get_property CONFIG.serial_flash_interface $libhandle]
|
||||
set ifaceselect 0
|
||||
set ps7qspi 0
|
||||
global spi_periphs_name_list
|
||||
foreach periph $spi_periphs_name_list {
|
||||
if {$periph == "axi_spi" || $periph == "axi_quad_spi"
|
||||
|| $periph == "opb_spi"
|
||||
|| $periph == "xps_insystem_flash"
|
||||
|| $periph == "xps_spi"} {
|
||||
if {$serial_flash_interface == 1} {
|
||||
puts $file_handle "\#define XPAR_XISF_INTERFACE_AXISPI 1"
|
||||
set ifaceselect 1
|
||||
}
|
||||
} elseif {$periph == "ps7_spi" &&
|
||||
$serial_flash_interface == 2} {
|
||||
puts $file_handle "\#define XPAR_XISF_INTERFACE_PSSPI 1"
|
||||
set ifaceselect 1
|
||||
} elseif {$periph == "ps7_qspi" &&
|
||||
$serial_flash_interface == 3} {
|
||||
puts $file_handle "\#define XPAR_XISF_INTERFACE_PSQSPI 1"
|
||||
set ifaceselect 1
|
||||
} elseif {$periph == "ps7_qspi"} {
|
||||
set ps7qspi 1
|
||||
}
|
||||
}
|
||||
|
||||
if {$ps7qspi == 1 && $ifaceselect == 0} {
|
||||
puts "WARN: Improper Flash Interface from BSP Settings!!!! Defaulting on 'ps7_qspi' interface"
|
||||
puts $file_handle "\#define XPAR_XISF_INTERFACE_PSQSPI 1"
|
||||
}
|
||||
|
||||
puts $file_handle ""
|
||||
close $file_handle
|
||||
|
||||
# Copy the include files to the include directory
|
||||
set srcdir [file join src include]
|
||||
set dstdir [file join .. .. include]
|
||||
|
||||
# Create dstdir if it does not exist
|
||||
if { ! [file exists $dstdir] } {
|
||||
file mkdir $dstdir
|
||||
}
|
||||
|
||||
# Get list of files in the srcdir
|
||||
set sources [glob -join $srcdir *.h]
|
||||
|
||||
# Copy each of the files in the list to dstdir
|
||||
foreach source $sources {
|
||||
file copy -force $source $dstdir
|
||||
}
|
||||
}
|
|
@ -0,0 +1,556 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
* XILINX 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 xilisf_atmel_buffer_rdwr_example.c
|
||||
*
|
||||
*
|
||||
* This file contains a design example using the Xilinx In-system and Serial
|
||||
* Flash Library (XilIsf). This example shows the Buffer Write, Buffer to Page
|
||||
* Program with Built-in Erase, Page to Buffer Transfer and Buffer Read features.
|
||||
*
|
||||
* This example
|
||||
* - Writes to a SRAM page buffer using Buffer Write feature
|
||||
* - Erase a Page and data is transferred to this page from the SRAM page buffer
|
||||
* using the Buffer to Page Program with Built-in Erase feature.
|
||||
* - Transfers the data to a SRAM Page using Page to Buffer Transfer feature.
|
||||
* - Reads back the Buffer that is written using the Buffer Read feature and
|
||||
* compares the data.
|
||||
*
|
||||
* The example works for AT45DB011D/AT45DB021D/AT45DB041D/AT45DB081D Serial Flash
|
||||
* devices. The bytes per page (ISF_PAGE_SIZE) in these devices is 264 for
|
||||
* Default addressing mode and 256 in Power-of-2 addressing mode.
|
||||
*
|
||||
* For AT45DB161D/AT45DB321D the Bytes Per Page (ISF_PAGE_SIZE) is 528 for
|
||||
* Default addressing mode and 512 in Power-Of-2 addressing mode.
|
||||
*
|
||||
* For AT45DB642D the Bytes Per Page (ISF_PAGE_SIZE) is 1056 for Default
|
||||
* addressing mode and 1024 in Power-Of-2 addressing mode.
|
||||
*
|
||||
* The ISF_PAGE_SIZE should be defined by the user according to the Device used.
|
||||
*
|
||||
* For further details of each device refer to the Spartan-3AN Serial Flash User
|
||||
* Guide and data sheets of Atmel AT45XXXD .
|
||||
*
|
||||
* This example has been tested with the In-system Flash Memory available on the
|
||||
* Spartan-3AN on a Xilinx Spartan-3AN Starter Kit board.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
*<pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ------- -------- ---------------------------------------------------
|
||||
* 1.00a ksu/sdm 03/22/08 First release
|
||||
* 2.00a ktn 11/22/09 Updated to use HAL processor APIs.
|
||||
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
|
||||
* instead of driver handler.
|
||||
*</pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xil_types.h"
|
||||
#include "xparameters.h" /* EDK generated parameters */
|
||||
#include "xintc.h" /* Interrupt controller device driver */
|
||||
#include <xilisf.h> /* Serial Flash Library header file */
|
||||
#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 Serial Flash device on the SPI bus, this signal is typically
|
||||
* connected to the chip select of the device.
|
||||
*/
|
||||
#define ISF_SPI_SELECT 0x01
|
||||
|
||||
/*
|
||||
* Page size of the Serial Flash.
|
||||
*/
|
||||
#define ISF_PAGE_SIZE 264
|
||||
|
||||
/*
|
||||
* Address of the page to perform Erase, Write and Read operations.
|
||||
*/
|
||||
#define TEST_ADDRESS 0xA3600
|
||||
|
||||
#define ISF_TEST_BYTE 0x28 /* Test Byte offset value written to Serial
|
||||
Flash */
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
static int IsfWaitForFlashNotBusy();
|
||||
|
||||
static int SetupInterruptSystem(XSpi *SpiPtr);
|
||||
|
||||
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount);
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
/*
|
||||
* The instances to support the device drivers are global such that the
|
||||
* are initialized to zero each time the program runs.
|
||||
*/
|
||||
static XIsf Isf;
|
||||
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; /* State of Spi Transfer */
|
||||
static int ErrorCount; /* Errors occurred during Spi transfers */
|
||||
|
||||
/*
|
||||
* The user needs to allocate a buffer to be used by the In-system and Serial
|
||||
* Flash Library to perform any read/write operations on the Serial Flash
|
||||
* device.
|
||||
* User applications must pass the address of this memory to the Library in
|
||||
* Serial Flash Initialization function, for the Library to work.
|
||||
* For Write operations:
|
||||
* - The size of this buffer should be equal to the Number of bytes to be
|
||||
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
|
||||
* - The size of this buffer should be large enough for usage across all the
|
||||
* applications that use a common instance of the Serial Flash.
|
||||
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
|
||||
* to the Serial Flash, through a single Write operation.
|
||||
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
|
||||
* application only reads from the Serial Flash (no write operations).
|
||||
*/
|
||||
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
|
||||
|
||||
/*
|
||||
* Buffers used during read and write transactions.
|
||||
*/
|
||||
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES] ; /* Read Buffer */
|
||||
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to execute the Atmel Serial Flash Buffer Read/Write example.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
******************************************************************************/
|
||||
int main(void)
|
||||
{
|
||||
int Status;
|
||||
u16 Index;
|
||||
XIsf_BufferWriteParam BufferWriteParam;
|
||||
XIsf_BufferToFlashWriteParam BufferToFlashWriteParam;
|
||||
XIsf_FlashToBufTransferParam FlashToBufTransferParam;
|
||||
XIsf_BufferReadParam BufferReadParam;
|
||||
|
||||
/*
|
||||
* Initialize the SPI driver so that it's ready to use,
|
||||
* specify the device ID that is generated in xparameters.h.
|
||||
*/
|
||||
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
|
||||
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.
|
||||
*/
|
||||
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
|
||||
|
||||
/*
|
||||
* Start the SPI driver so that interrupts and the device are enabled.
|
||||
*/
|
||||
Status = XSpi_Start(&Spi);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the In-system and Serial Flash Library.
|
||||
*/
|
||||
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set The transfer Mode to Interrupt
|
||||
*/
|
||||
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - SRAM page buffer number where the data is to be written.
|
||||
* - Byte offset within SRAM page buffer where the data is to be written
|
||||
* - The number of bytes to be written.
|
||||
* - The Write Buffer with the data to be written.
|
||||
*/
|
||||
BufferWriteParam.BufferNum = XISF_PAGE_BUFFER1;
|
||||
BufferWriteParam.ByteOffset = 0;
|
||||
BufferWriteParam.NumBytes = ISF_PAGE_SIZE;
|
||||
BufferWriteParam.WritePtr = WriteBuffer;
|
||||
|
||||
/*
|
||||
* Prepare the write buffer. Fill in the data need to be written into
|
||||
* Serial Flash.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
BufferWriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write to SRAM Page buffer.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Write(&Isf, XISF_BUFFER_WRITE, (void*) &BufferWriteParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - SRAM page buffer number from where the data is to be written.
|
||||
* - Page Address in the Serial Flash where the data is to be written.
|
||||
*/
|
||||
BufferToFlashWriteParam.BufferNum = XISF_PAGE_BUFFER1;
|
||||
BufferToFlashWriteParam.Address = TEST_ADDRESS;
|
||||
|
||||
/*
|
||||
* Perform Erase then Write to Serial Flash from the SRAM page buffer.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Write(&Isf, XISF_BUF_TO_PAGE_WRITE_WITH_ERASE,
|
||||
(void*) &BufferToFlashWriteParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Serial Flash is ready to accept next command.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - SRAM page buffer number to which the data is to be read.
|
||||
* - Set the Page Address from where the data is to be transferred.
|
||||
*/
|
||||
FlashToBufTransferParam.BufferNum = XISF_PAGE_BUFFER1;
|
||||
FlashToBufTransferParam.Address = TEST_ADDRESS;
|
||||
|
||||
/*
|
||||
* Transfer data from the Serial Flash to the SRAM page buffer.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Read(&Isf, XISF_PAGE_TO_BUF_TRANS,
|
||||
(void*) &FlashToBufTransferParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Serial Flash is ready to accept next command.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - SRAM page buffer number where the data is to be read.
|
||||
* - Byte offset within SRAM page buffer where the data is to be read.
|
||||
* - The number of bytes to be read.
|
||||
* - The Read Buffer to which with the data is to be read.
|
||||
*/
|
||||
BufferReadParam.BufferNum = XISF_PAGE_BUFFER1;
|
||||
BufferReadParam.ByteOffset = 0;
|
||||
BufferReadParam.NumBytes = ISF_PAGE_SIZE;
|
||||
BufferReadParam.ReadPtr = ReadBuffer;
|
||||
|
||||
/*
|
||||
* Read data from SRAM page buffer.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Read(&Isf, XISF_BUFFER_READ, (void*) &BufferReadParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the data read against the data written.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function waits till the Atmel Serial Flash is ready to accept next
|
||||
* command.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int IsfWaitForFlashNotBusy()
|
||||
{
|
||||
int Status;
|
||||
u8 StatusReg;
|
||||
|
||||
while(1) {
|
||||
|
||||
/*
|
||||
* Get the Status Register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_GetStatus(&Isf, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the Serial Flash is ready to accept the next
|
||||
* command. If so break.
|
||||
*/
|
||||
StatusReg = ReadBuffer[1];
|
||||
if(StatusReg & XISF_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, u16 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, specify real mode so that the SPI
|
||||
* can cause interrupts through 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;
|
||||
}
|
|
@ -0,0 +1,331 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
* XILINX 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 xilisf_atmel_rdwr_polled_example.c
|
||||
*
|
||||
* This file contains a design example using the In-system and Serial Flash
|
||||
* Library (XilIsf) with the Spi driver in polled mode of operation. This example
|
||||
* shows the Erase, Read and Write features.
|
||||
*
|
||||
* This example
|
||||
* - Erases a Page
|
||||
* - Writes to the erased Page
|
||||
* - Reads back the Page that is written and compares the data
|
||||
*
|
||||
* The example works for AT45DB011D/AT45DB021D/AT45DB041D/AT45DB081D Serial Flash
|
||||
* devices. The bytes per page (ISF_PAGE_SIZE) in these devices is
|
||||
* 264 for Default addressing mode and 256 in Power-of-2 addressing mode.
|
||||
*
|
||||
* For AT45DB161D/AT45DB321D devices the Bytes Per Page (ISF_PAGE_SIZE) is
|
||||
* 528 for Default addressing mode and 512 in Power-Of-2 addressing mode.
|
||||
*
|
||||
* For AT45DB642D device the Bytes Per Page (ISF_PAGE_SIZE) is 1056 for Default
|
||||
* addressing mode and 1024 in Power-Of-2 addressing mode.
|
||||
*
|
||||
* The ISF_PAGE_SIZE should be defined by the user according to the Device used.
|
||||
*
|
||||
* For further details of each device refer to the Spartan-3AN Serial Flash User
|
||||
* Guide and data sheets of Atmel AT45XXXD .
|
||||
*
|
||||
* This example has been tested with the In-System Flash Memory available on the
|
||||
* Spartan-3AN on a Xilinx Spartan-3AN Starter Kit board.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
*<pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- --- -------- ---------------------------------------------------
|
||||
* 1.00a sdm 04/02/08 First release
|
||||
* 2.00a ktn 11/22/09 The Spi Driver APIs have changed. Replaced the call
|
||||
* to XSpi_mIntrGlobalDisable with XSpi_IntrGlobalDisable.
|
||||
*</pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h" /* EDK generated parameters */
|
||||
#include "xilisf.h" /* Serial Flash Library header file */
|
||||
|
||||
/************************** 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
|
||||
|
||||
/*
|
||||
* The following constant defines the slave select signal that is used to
|
||||
* select the Serial Flash device on the SPI bus, this signal is typically
|
||||
* connected to the chip select of the device.
|
||||
*/
|
||||
#define ISF_SPI_SELECT 0x01
|
||||
|
||||
/*
|
||||
* Page size of the Serial Flash.
|
||||
*/
|
||||
#define ISF_PAGE_SIZE 264
|
||||
|
||||
/*
|
||||
* Address within the page of the Serial Flash to perform Erase, Write and Read
|
||||
* operations.
|
||||
*/
|
||||
#define TEST_ADDRESS 0xA2400
|
||||
#define ISF_TEST_BYTE 0x20 /* Test Byte offset value written */
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
static int IsfWaitForFlashNotBusy();
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
/*
|
||||
* The instances to support the device drivers are global such that they
|
||||
* are initialized to zero each time the program runs.
|
||||
*/
|
||||
static XIsf Isf;
|
||||
static XSpi Spi;
|
||||
|
||||
/*
|
||||
* The user needs to allocate a buffer to be used by the In-system and Serial
|
||||
* Flash Library to perform any read/write operations on the Serial Flash
|
||||
* device.
|
||||
* User applications must pass the address of this memory to the Library in
|
||||
* Serial Flash Initialization function, for the Library to work.
|
||||
* For Write operations:
|
||||
* - The size of this buffer should be equal to the Number of bytes to be
|
||||
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
|
||||
* - The size of this buffer should be large enough for usage across all the
|
||||
* applications that use a common instance of the Serial Flash.
|
||||
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
|
||||
* to the Serial Flash, through a single Write operation.
|
||||
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
|
||||
* application only reads from the Serial Flash (no write operations).
|
||||
*/
|
||||
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
|
||||
|
||||
/*
|
||||
* Buffers used during read and write transactions.
|
||||
*/
|
||||
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES] ; /* Read Buffer */
|
||||
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to execute the Atmel Serial Flash Read/Write polled example.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int main(void)
|
||||
{
|
||||
int Status;
|
||||
u16 Index;
|
||||
XIsf_WriteParam WriteParam;
|
||||
XIsf_ReadParam ReadParam;
|
||||
u32 Address;
|
||||
|
||||
/*
|
||||
* Initialize the SPI driver so that it's ready to use,
|
||||
* specify the device ID that is generated in xparameters.h.
|
||||
*/
|
||||
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the SPI driver so that the device is enabled.
|
||||
*/
|
||||
Status = XSpi_Start(&Spi);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable Global interrupt to use the Spi driver in polled mode
|
||||
* operation.
|
||||
*/
|
||||
XSpi_IntrGlobalDisable(&Spi);
|
||||
|
||||
/*
|
||||
* Initialize the In-system and Serial Flash Library.
|
||||
*/
|
||||
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Specify the address in the Serial Flash for the Erase/Write/Read
|
||||
* operations.
|
||||
*/
|
||||
Address = TEST_ADDRESS;
|
||||
|
||||
/*
|
||||
* Perform the Page Erase operation.
|
||||
*/
|
||||
Status = XIsf_Erase(&Isf, XISF_PAGE_ERASE, Address);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Serial Flash is ready.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address within the Serial Flash where the data is to be written.
|
||||
* - The number of bytes to be written to the Serial Flash.
|
||||
* - Write Buffer which contains the data to be written to the Serial
|
||||
* Flash.
|
||||
*/
|
||||
WriteParam.Address = Address;
|
||||
WriteParam.NumBytes = ISF_PAGE_SIZE;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
|
||||
/*
|
||||
* Prepare the write buffer. Fill in the data need to be written into
|
||||
* Serial Flash.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write operation.
|
||||
*/
|
||||
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Serial Flash is ready.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ISF_PAGE_SIZE;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
|
||||
/*
|
||||
* Perform the Read operation.
|
||||
*/
|
||||
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the Data Read with the Data Written to the Serial Flash.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadParam.ReadPtr[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function waits till the Serial Flash is ready to accept next command.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int IsfWaitForFlashNotBusy()
|
||||
{
|
||||
int Status;
|
||||
u8 StatusReg;
|
||||
u8 ReadBuffer[2];
|
||||
|
||||
while(1) {
|
||||
|
||||
/*
|
||||
* Get the Status Register.
|
||||
*/
|
||||
Status = XIsf_GetStatus(&Isf, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the Serial Flash is ready to accept the next
|
||||
* command. If so break.
|
||||
*/
|
||||
StatusReg = ReadBuffer[BYTE2];
|
||||
if(StatusReg & XISF_SR_IS_READY_MASK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,515 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
* XILINX 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 xilisf_atmel_read_write_example.c
|
||||
*
|
||||
* This file contains a design example using the In-system and Serial Flash
|
||||
* Library (XilIsf). This example shows the Erase, Read and Write features.
|
||||
*
|
||||
* This example
|
||||
* - Erases a Page
|
||||
* - Writes to the erased Page
|
||||
* - Reads back the Page that is written and compares the data.
|
||||
*
|
||||
* The example works for AT45DB011D/AT45DB021D/AT45DB041D/AT45DB081D Serial Flash
|
||||
* devices. The bytes per page (ISF_PAGE_SIZE) in these devices is
|
||||
* 264 for Default addressing mode and 256 in Power-of-2 addressing mode.
|
||||
*
|
||||
* For AT45DB161D/AT45DB321D devices the Bytes Per Page (ISF_PAGE_SIZE) is
|
||||
* 528 for Default addressing mode and 512 in Power-Of-2 addressing mode.
|
||||
*
|
||||
* For AT45DB642D device the Bytes Per Page (ISF_PAGE_SIZE) is 1056 for Default
|
||||
* addressing mode and 1024 in Power-Of-2 addressing mode.
|
||||
*
|
||||
* The ISF_PAGE_SIZE should be defined by the user according to the Device used.
|
||||
*
|
||||
* For further details of each device refer to the Spartan-3AN Serial Flash User
|
||||
* Guide and data sheets of Atmel AT45XXXD .
|
||||
*
|
||||
* This example has been tested with the In-System Flash Memory available on the
|
||||
* Spartan-3AN on a Xilinx Spartan-3AN Starter Kit board.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
*<pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ------- -------- ---------------------------------------------------
|
||||
* 1.00a mta/ksu 03/20/08 First release
|
||||
* 2.00a ktn 11/22/09 Updated to use HAL processor APIs.
|
||||
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
|
||||
* instead of driver handler.
|
||||
*</pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h" /* EDK generated parameters */
|
||||
#include "xintc.h" /* Interrupt controller device driver */
|
||||
#include <xilisf.h> /* Serial Flash Library header file */
|
||||
#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
|
||||
* select the Serial Flash device on the SPI bus, this signal is typically
|
||||
* connected to the chip select of the device.
|
||||
*/
|
||||
#define ISF_SPI_SELECT 0x01
|
||||
|
||||
/*
|
||||
* Page size of the Serial Flash.
|
||||
*/
|
||||
#define ISF_PAGE_SIZE 264
|
||||
|
||||
/*
|
||||
* Address within the page of the Serial Flash to perform Erase, Write and Read
|
||||
* operations.
|
||||
*/
|
||||
#define TEST_ADDRESS 0xA2400
|
||||
#define ISF_TEST_BYTE 0x30 /* Test Byte offset value written */
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
static int IsfWaitForFlashNotBusy();
|
||||
|
||||
static int SetupInterruptSystem(XSpi *SpiPtr);
|
||||
|
||||
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount);
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
/*
|
||||
* The instances to support the device drivers are global such that they
|
||||
* are initialized to zero each time the program runs.
|
||||
*/
|
||||
static XIsf Isf;
|
||||
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; /* State of Spi Transfer */
|
||||
static int ErrorCount; /* Errors occurred during Spi transfers */
|
||||
|
||||
/*
|
||||
* The user needs to allocate a buffer to be used by the In-system and Serial
|
||||
* Flash Library to perform any read/write operations on the Serial Flash
|
||||
* device.
|
||||
* User applications must pass the address of this memory to the Library in
|
||||
* Serial Flash Initialization function, for the Library to work.
|
||||
* For Write operations:
|
||||
* - The size of this buffer should be equal to the Number of bytes to be
|
||||
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
|
||||
* - The size of this buffer should be large enough for usage across all the
|
||||
* applications that use a common instance of the Serial Flash.
|
||||
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
|
||||
* to the Serial Flash, through a single Write operation.
|
||||
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
|
||||
* application only reads from the Serial Flash (no write operations).
|
||||
*/
|
||||
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
|
||||
|
||||
/*
|
||||
* Buffers used during read and write transactions.
|
||||
*/
|
||||
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES] ; /* Read Buffer */
|
||||
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to execute the Atmel Serial Flash Read/Write example.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int main(void)
|
||||
{
|
||||
int Status;
|
||||
u16 Index;
|
||||
XIsf_WriteParam WriteParam;
|
||||
XIsf_ReadParam ReadParam;
|
||||
u32 Address;
|
||||
|
||||
/*
|
||||
* Initialize the SPI driver so that it's ready to use,
|
||||
* specify the device ID that is generated in xparameters.h.
|
||||
*/
|
||||
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
|
||||
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.
|
||||
*/
|
||||
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
|
||||
|
||||
/*
|
||||
* Start the SPI driver so that interrupts and the device are enabled.
|
||||
*/
|
||||
Status = XSpi_Start(&Spi);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the In-system and Serial Flash Library.
|
||||
*/
|
||||
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set The transfer Mode to Interrupt
|
||||
*/
|
||||
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
|
||||
|
||||
/*
|
||||
* Specify the address in the Serial Flash for the Erase/Write/Read
|
||||
* operations.
|
||||
*/
|
||||
Address = TEST_ADDRESS;
|
||||
|
||||
/*
|
||||
* Perform the Page Erase operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Erase(&Isf, XISF_PAGE_ERASE, Address);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Serial Flash is ready.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address within the Serial Flash where the data is to be written.
|
||||
* - The number of bytes to be written to the Serial Flash.
|
||||
* - Write Buffer which contains the data to be written to the Serial
|
||||
* Flash.
|
||||
*/
|
||||
WriteParam.Address = Address;
|
||||
WriteParam.NumBytes = ISF_PAGE_SIZE;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
|
||||
/*
|
||||
* Prepare the write buffer. Fill in the data need to be written into
|
||||
* Serial Flash.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Serial Flash is ready.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ISF_PAGE_SIZE;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
|
||||
/*
|
||||
* Perform the Read operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the Data Read with the Data Written to the Serial Flash.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadParam.ReadPtr[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function waits till the Serial Flash is ready to accept next command.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int IsfWaitForFlashNotBusy()
|
||||
{
|
||||
int Status;
|
||||
u8 StatusReg;
|
||||
u8 ReadBuffer[2];
|
||||
|
||||
while(1) {
|
||||
|
||||
/*
|
||||
* Get the Status Register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_GetStatus(&Isf, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the Serial Flash is ready to accept the next
|
||||
* command. If so break.
|
||||
*/
|
||||
StatusReg = ReadBuffer[BYTE2];
|
||||
if(StatusReg & XISF_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, u16 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, specify real mode so that the SPI
|
||||
* can cause interrupts through 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;
|
||||
}
|
786
lib/sw_services/xilisf/examples/xilisf_atmel_spr_example.c
Normal file
786
lib/sw_services/xilisf/examples/xilisf_atmel_spr_example.c
Normal file
|
@ -0,0 +1,786 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
* XILINX 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 xilisf_atmel_spr_example.c
|
||||
*
|
||||
*
|
||||
* This file contains a design example using the In-system and Serial Flash
|
||||
* Library (XilIsf). This example shows all the features related to Sector
|
||||
* Protection.
|
||||
*
|
||||
* This example
|
||||
* - Writes to the Sector Protection Register
|
||||
* - Reads the Sector Protection Register and compares with the data that was
|
||||
* written
|
||||
* - Erases the Sector Protection Register
|
||||
* - Erases a Page and writes the data to the Page
|
||||
* - Enables the Sector Protection so that all the sectors are Write protected
|
||||
* - Erases a Page (This should not happen as the Sectors are Write protected
|
||||
* - Reads back the Page that is written and compares the data.
|
||||
*
|
||||
* The example works for AT45DB011D/AT45DB021D/AT45DB041D/AT45DB081D Serial Flash
|
||||
* devices. The bytes per page (ISF_PAGE_SIZE) in these devices is
|
||||
* 264 for Default addressing mode and 256 in Power-of-2 addressing mode.
|
||||
*
|
||||
* For AT45DB161D/AT45DB321D devices the Bytes Per Page (ISF_PAGE_SIZE) is
|
||||
* 528 for Default addressing mode and 512 in Power-Of-2 addressing mode.
|
||||
*
|
||||
* For AT45DB642D device the Bytes Per Page (ISF_PAGE_SIZE) is 1056 for Default
|
||||
* addressing mode and 1024 in Power-Of-2 addressing mode.
|
||||
*
|
||||
* The ISF_PAGE_SIZE should be defined by the user according to the Device used.
|
||||
*
|
||||
* For further details of each device refer to the Spartan-3AN Serial Flash User
|
||||
* Guide and data sheets of Atmel AT45XXXD .
|
||||
*
|
||||
* This example has been tested with the In-System Flash Memory available on the
|
||||
* Spartan-3AN on a Xilinx Spartan-3AN Starter Kit board.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
*<pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ------- -------- -----------------------------------------------------
|
||||
* 1.00a mta/ksu 03/20/08 First release
|
||||
* 1.00a ktn 09/08/09 Updated this example such that every SPR write should
|
||||
* be preceded by an erase as per the atmel datasheet.
|
||||
* 2.00a ktn 11/22/09 Updated to use HAL processor APIs.
|
||||
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
|
||||
* instead of driver handler.
|
||||
*</pre>
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h" /* EDK generated parameters */
|
||||
#include "xintc.h" /* Interrupt controller device driver */
|
||||
#include <xilisf.h> /* Serial Flash Library header file */
|
||||
#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
|
||||
* select the Serial Flash device on the SPI bus, this signal is typically
|
||||
* connected to the chip select of the device.
|
||||
*/
|
||||
#define ISF_SPI_SELECT 0x01
|
||||
|
||||
/*
|
||||
* Page size of the Serial Flash.
|
||||
*/
|
||||
#define ISF_PAGE_SIZE 264
|
||||
|
||||
/*
|
||||
* Address within the page of the Serial Flash to perform Erase, Write and Read
|
||||
* operations.
|
||||
*/
|
||||
#define TEST_ADDRESS 0xA2400
|
||||
#define ISF_TEST_BYTE 0x36 /* Test Byte offset value */
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
static int IsfWaitForFlashNotBusy();
|
||||
|
||||
static int SetupInterruptSystem(XSpi *SpiPtr);
|
||||
|
||||
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount);
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
/*
|
||||
* The instances to support the device drivers are global such that they
|
||||
* are initialized to zero each time the program runs.
|
||||
*/
|
||||
static XIsf Isf;
|
||||
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; /* State of Spi Transfer */
|
||||
static int ErrorCount; /* Errors occurred during Spi transfers */
|
||||
|
||||
/*
|
||||
* The user needs to allocate a buffer to be used by the In-system and Serial
|
||||
* Flash Library to perform any read/write operations on the Serial Flash
|
||||
* device.
|
||||
* User applications must pass the address of this memory to the Library in
|
||||
* Serial Flash Initialization function, for the Library to work.
|
||||
* For Write operations:
|
||||
* - The size of this buffer should be equal to the Number of bytes to be
|
||||
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
|
||||
* - The size of this buffer should be large enough for usage across all the
|
||||
* applications that use a common instance of the Serial Flash.
|
||||
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
|
||||
* to the Serial Flash, through a single Write operation.
|
||||
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
|
||||
* application only reads from the Serial Flash (no write operations).
|
||||
*/
|
||||
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
|
||||
|
||||
/*
|
||||
* Buffers used during read and write transactions.
|
||||
*/
|
||||
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES] ; /* Read Buffer. */
|
||||
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer. */
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to execute the Atmel Serial Flash SPR example.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
******************************************************************************/
|
||||
int main(void)
|
||||
{
|
||||
int Status;
|
||||
u16 Index;
|
||||
XIsf_WriteParam WriteParam;
|
||||
XIsf_ReadParam ReadParam;
|
||||
|
||||
/*
|
||||
* Initialize the SPI driver so that it's ready to use,
|
||||
* specify the device ID that is generated in xparameters.h.
|
||||
*/
|
||||
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
|
||||
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.
|
||||
*/
|
||||
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
|
||||
|
||||
/*
|
||||
* Start the SPI driver so that interrupts and the device are enabled.
|
||||
*/
|
||||
Status = XSpi_Start(&Spi);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the In-system and Serial Flash Library.
|
||||
*/
|
||||
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set The transfer Mode to Interrupt
|
||||
*/
|
||||
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
|
||||
|
||||
/*
|
||||
* Perform the SPR erase operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_ERASE, NULL);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Serial Flash is ready.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the SPR read operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the values read back from the SPR with the values written
|
||||
* during SPR erase operation. Return if error.
|
||||
*/
|
||||
for(Index = 0; Index < Isf.NumOfSectors; Index++) {
|
||||
if((ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] & 0xFF) !=
|
||||
0xFF) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare the values to be written to the Sector Protect Register
|
||||
* (SPR).
|
||||
*/
|
||||
for(Index = 0; Index < Isf.NumOfSectors; Index++) {
|
||||
WriteBuffer[Index] = 0x00;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the SPR write operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Serial Flash is ready.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the SPR read operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the values read back from the SPR with the values written
|
||||
* during SPR write operation. Return if error.
|
||||
*/
|
||||
for(Index = 0; Index < Isf.NumOfSectors; Index++) {
|
||||
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] != 0x00) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the SPR erase operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_ERASE, NULL);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
ErrorCount = 0;
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Serial Flash is ready.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the SPR read operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the values read from the SPR, are all 0xFF after performing
|
||||
* the SPR erase operation.
|
||||
*/
|
||||
for(Index = XISF_CMD_SEND_EXTRA_BYTES; Index < (Isf.NumOfSectors +
|
||||
XISF_CMD_SEND_EXTRA_BYTES); Index++) {
|
||||
if(ReadBuffer[Index] != 0xFF) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the SP disable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SP_DISABLE, NULL);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Serial Flash is ready.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Page Erase operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Erase(&Isf, XISF_PAGE_ERASE, TEST_ADDRESS);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Serial Flash is ready.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address within the Serial Flash where the data is to be written.
|
||||
* - The number of bytes to be written to the Serial Flash.
|
||||
* - Write Buffer which contains the data to be written to the Serial
|
||||
* Flash.
|
||||
*/
|
||||
WriteParam.Address = TEST_ADDRESS;
|
||||
WriteParam.NumBytes = ISF_PAGE_SIZE;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
|
||||
/*
|
||||
* Prepare the write buffer. Fill in the data need to be written into
|
||||
* Serial Flash.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Serial Flash is ready.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the SP enable operation. This should enable protection for
|
||||
* all sectors since a SP erase operation has been performed earlier.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SP_ENABLE, NULL);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Serial Flash is ready.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Page Erase operation. The Page Erase operation should not
|
||||
* work since SP is enabled.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Erase(&Isf, XISF_PAGE_ERASE, TEST_ADDRESS);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Serial Flash is ready.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the SP disable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SP_DISABLE, NULL);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Serial Flash is ready.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
*/
|
||||
ReadParam.Address = TEST_ADDRESS;
|
||||
ReadParam.NumBytes = ISF_PAGE_SIZE;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
|
||||
/*
|
||||
* Perform the read operation. The values read should be same as the
|
||||
* values written earlier.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the data read against the data written.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadParam.ReadPtr[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function waits till the Serial Flash is ready to accept next command.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int IsfWaitForFlashNotBusy()
|
||||
{
|
||||
int Status;
|
||||
u8 StatusReg;
|
||||
u8 ReadBuffer[2];
|
||||
|
||||
while(1) {
|
||||
|
||||
/*
|
||||
* Get the Status Register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_GetStatus(&Isf, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the Serial Flash is ready to accept the next
|
||||
* command. If so break.
|
||||
*/
|
||||
StatusReg = ReadBuffer[BYTE2];
|
||||
if(StatusReg & XISF_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, u16 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;
|
||||
}
|
511
lib/sw_services/xilisf/examples/xilisf_intel_otp_rdwr_example.c
Normal file
511
lib/sw_services/xilisf/examples/xilisf_intel_otp_rdwr_example.c
Normal file
|
@ -0,0 +1,511 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
* XILINX 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 xilisf_intel_otp_rdwr_example.c
|
||||
*
|
||||
* This file contains a design example using the Xilinx In-system and Serial
|
||||
* Flash Library (XilIsf). This example shows the One-Time Programmable (OTP)
|
||||
* Read/Write features.
|
||||
*
|
||||
* This example
|
||||
* - Writes a Byte to OTP region
|
||||
* - Reads back the Byte written to the OTP region and compares the data
|
||||
*
|
||||
* This example has been tested with Intel (Numonyx) Serial Flash Memory (S33)
|
||||
* on a S3A-DSP starter kit. For further details about the S33 Flash device refer
|
||||
* to the Intel (Numonyx) Serial Flash Memory (S33) Data sheets.
|
||||
*
|
||||
*
|
||||
* @note
|
||||
*
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -----------------------------------------------
|
||||
* 1.00a sdm 03/24/08 First release
|
||||
* 2.00a ktn 11/22/09 Updated to use HAL processor APIs.
|
||||
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
|
||||
* instead of driver handler.
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h" /* EDK generated parameters */
|
||||
#include "xintc.h" /* Interrupt controller device driver */
|
||||
#include <xilisf.h> /* Serial Flash Library header file */
|
||||
#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 ISF_SPI_SELECT 0x01
|
||||
|
||||
/*
|
||||
* Number of bytes to be written to the OTP area of the Serial Flash.
|
||||
*/
|
||||
#define ISF_OTP_WRITE_SIZE 256
|
||||
|
||||
/*
|
||||
* Address of the page to perform Erase, Write and Read operations.
|
||||
*/
|
||||
#define ISF_OTP_TEST_ADDRESS 0x0225;
|
||||
#define ISF_TEST_BYTE 0x30 /* Test Byte offset value written */
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
static int IsfWaitForFlashNotBusy(void);
|
||||
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 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 XIsf Isf;
|
||||
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; /* State of Spi Transfer */
|
||||
static int ErrorCount; /* Errors occurred during Spi transfers */
|
||||
|
||||
/*
|
||||
* The user needs to allocate a buffer to be used by the In-system and Serial
|
||||
* Flash Library to perform any read/write operations on the Serial Flash
|
||||
* device.
|
||||
* User applications must pass the address of this memory to the Library in
|
||||
* Serial Flash Initialization function, for the Library to work.
|
||||
* For Write operations:
|
||||
* - The size of this buffer should be equal to the Number of bytes to be
|
||||
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
|
||||
* - The size of this buffer should be large enough for usage across all the
|
||||
* applications that use a common instance of the Serial Flash.
|
||||
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
|
||||
* to the Serial Flash, through a single Write operation.
|
||||
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
|
||||
* application only reads from the Serial Flash (no write operations).
|
||||
*/
|
||||
u8 IsfWriteBuffer[ISF_OTP_WRITE_SIZE + XISF_OTP_RDWR_EXTRA_BYTES];
|
||||
|
||||
/*
|
||||
* Buffers used during read and write transactions.
|
||||
*/
|
||||
u8 ReadBuffer[ISF_OTP_WRITE_SIZE + XISF_OTP_RDWR_EXTRA_BYTES]; /* Read Buffer */
|
||||
u8 WriteBuffer[ISF_OTP_WRITE_SIZE]; /* Write Buffer */
|
||||
|
||||
/************************** Function Definitions ******************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to execute the Intel OTP Read/Write Flash example.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
******************************************************************************/
|
||||
int main()
|
||||
{
|
||||
int Status;
|
||||
u32 Address;
|
||||
XIsf_WriteParam WriteParam;
|
||||
XIsf_ReadParam ReadParam;
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the SPI driver so that it's ready to use,
|
||||
* specify the device ID that is generated in xparameters.h.
|
||||
*/
|
||||
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
|
||||
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.
|
||||
*/
|
||||
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
|
||||
|
||||
/*
|
||||
* Start the SPI driver so that interrupts and the device are enabled.
|
||||
*/
|
||||
XSpi_Start(&Spi);
|
||||
|
||||
/*
|
||||
* Initialize the In-system and Serial Flash Library.
|
||||
*/
|
||||
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set The transfer Mode to Interrupt
|
||||
*/
|
||||
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
|
||||
|
||||
/*
|
||||
* Specify the address in the OTP region of the Serial Flash for the
|
||||
* Write/Read operations.
|
||||
*/
|
||||
Address = ISF_OTP_TEST_ADDRESS;
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address within the OTP region of the Serial Flash where the data is
|
||||
* to be written.
|
||||
* - The number of bytes to be written to the Serial Flash, this is
|
||||
* always 1 as only 1 byte can be written.
|
||||
* - Write Buffer which contains the data to be written to the OTP
|
||||
* region of the Serial Flash.
|
||||
*/
|
||||
WriteParam.Address = Address;
|
||||
WriteParam.NumBytes = ISF_OTP_WRITE_SIZE;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
|
||||
/*
|
||||
* Prepare the write buffer. Fill in the data need to be written into
|
||||
* the OTP region of the Serial Flash.
|
||||
*/
|
||||
WriteParam.WritePtr[BYTE1] = ISF_TEST_BYTE;
|
||||
|
||||
/*
|
||||
* Perform the OTP Write operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Write(&Isf, XISF_OTP_WRITE, (void*) &WriteParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address in the OTP region of the Serial Flash where the data is to
|
||||
* be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ISF_OTP_WRITE_SIZE;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
|
||||
/*
|
||||
* Perform the OTP read operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Read(&Isf, XISF_OTP_READ, (void*) &ReadParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the data read against the data Written.
|
||||
*/
|
||||
if(ReadBuffer[BYTE1 + XISF_OTP_RDWR_EXTRA_BYTES] !=
|
||||
(u8)(ISF_TEST_BYTE)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function waits till the Intel serial Flash is ready to accept the next
|
||||
* command.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note This function reads the Status Register of the Serial Flash and
|
||||
* waits till the WIP bit of the Status Register becomes 0.
|
||||
*
|
||||
******************************************************************************/
|
||||
int IsfWaitForFlashNotBusy(void)
|
||||
{
|
||||
int Status;
|
||||
u8 StatusReg;
|
||||
|
||||
while(1) {
|
||||
|
||||
/*
|
||||
* Get the Status Register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_GetStatus(&Isf, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for any errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the flash is ready to accept the next command.
|
||||
* If so break.
|
||||
*/
|
||||
StatusReg = ReadBuffer[BYTE2];
|
||||
if((StatusReg & XISF_SR_IS_READY_MASK) == 0) {
|
||||
|
||||
/*
|
||||
* If there were errors return XST_FAILURE.
|
||||
*/
|
||||
if (StatusReg & (XISF_SR_PROG_FAIL_MASK |
|
||||
XISF_SR_ERASE_FAIL_MASK)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
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, u16 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, specify real mode so that
|
||||
* the SPI can cause interrupts through 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;
|
||||
}
|
|
@ -0,0 +1,425 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
* XILINX 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 xilisf_intel_rdwr_polled_example.c
|
||||
*
|
||||
* This file contains a design example using the Xilinx In-system and Serial
|
||||
* Flash Library (XilIsf) with the Spi driver in polled mode of operation.
|
||||
* This example shows the Sector Protection Register Read, Sector Protection
|
||||
* Register Write, Sector Erase, Read and Write features.
|
||||
*
|
||||
* This example
|
||||
* - Disables the Sector Protection for all the Sectors
|
||||
* - Erases a Sector
|
||||
* - Writes to a Page within the Erased Sector
|
||||
* - Reads back the Page that is written and compares the data.
|
||||
*
|
||||
* This example has been tested with Intel (Numonyx) Serial Flash Memory (S33)
|
||||
* on a S3A-DSP starter kit. For further details about the S33 Flash device refer
|
||||
* to the Intel (Numonyx) Serial Flash Memory (S33) Data sheets.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- --- -------- -----------------------------------------------
|
||||
* 1.00a sdm 04/02/08 First release
|
||||
* 2.00a ktn 11/22/09 The Spi Driver APIs have changed. Replaced the call
|
||||
* to XSpi_mIntrGlobalDisable with XSpi_IntrGlobalDisable.
|
||||
*
|
||||
* </pre>
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h" /* EDK generated parameters */
|
||||
#include "xilisf.h" /* Serial Flash Library header file */
|
||||
|
||||
|
||||
/************************** 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
|
||||
|
||||
/*
|
||||
* 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 ISF_SPI_SELECT 0x01
|
||||
|
||||
/*
|
||||
* Number of bytes per page in the flash device.
|
||||
*/
|
||||
#define ISF_PAGE_SIZE 256
|
||||
|
||||
/*
|
||||
* Address of the page to perform Erase, Write and Read operations.
|
||||
*/
|
||||
#define ISF_TEST_ADDRESS 0x010000;
|
||||
#define ISF_TEST_BYTE 0x20 /* Test Byte offset value written */
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
static int IsfWaitForFlashNotBusy(void);
|
||||
|
||||
/************************** 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 XIsf Isf;
|
||||
static XSpi Spi;
|
||||
|
||||
/*
|
||||
* The user needs to allocate a buffer to be used by the In-system and Serial
|
||||
* Flash Library to perform any read/write operations on the Serial Flash
|
||||
* device.
|
||||
* User applications must pass the address of this memory to the Library in
|
||||
* Serial Flash Initialization function, for the Library to work.
|
||||
* For Write operations:
|
||||
* - The size of this buffer should be equal to the Number of bytes to be
|
||||
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
|
||||
* - The size of this buffer should be large enough for usage across all the
|
||||
* applications that use a common instance of the Serial Flash.
|
||||
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
|
||||
* to the Serial Flash, through a single Write operation.
|
||||
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
|
||||
* application only reads from the Serial Flash (no write operations).
|
||||
*/
|
||||
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
|
||||
|
||||
/*
|
||||
* Buffers used during read and write transactions.
|
||||
*/
|
||||
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; /* Read Buffer */
|
||||
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
|
||||
|
||||
/************************** Function Definitions ******************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to execute the Intel Serial Flash Read/Write polled example.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
******************************************************************************/
|
||||
int main()
|
||||
{
|
||||
int Status;
|
||||
u32 Index;
|
||||
u32 Address;
|
||||
XIsf_WriteParam WriteParam;
|
||||
XIsf_ReadParam ReadParam;
|
||||
|
||||
/*
|
||||
* Initialize the SPI driver so that it's ready to use,
|
||||
* specify the device ID that is generated in xparameters.h.
|
||||
*/
|
||||
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the SPI driver so that device is enabled.
|
||||
*/
|
||||
XSpi_Start(&Spi);
|
||||
|
||||
/*
|
||||
* Disable Global interrupt to use the Spi driver in polled mode
|
||||
* operation.
|
||||
*/
|
||||
XSpi_IntrGlobalDisable(&Spi);
|
||||
|
||||
/*
|
||||
* Initialize the In-system and Serial Flash Library.
|
||||
*/
|
||||
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following code Disables the Sector Protection for all the Blocks
|
||||
* in the Intel Serial Flash.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is Not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the Sector Protection Register.
|
||||
*/
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Clear all the Block protection bits in the Sector Protection
|
||||
* Register.
|
||||
*/
|
||||
WriteBuffer[BYTE1] = ReadBuffer[BYTE2] &
|
||||
(~(XISF_SR_BLOCK_PROTECT_MASK));
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Specify the address in the Serial Flash for the Erase/Write/Read
|
||||
* operations.
|
||||
*/
|
||||
Address = ISF_TEST_ADDRESS;
|
||||
|
||||
|
||||
/*
|
||||
* The following code Erases a Sector in the Intel Serial Flash.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Sector Erase operation.
|
||||
*/
|
||||
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The following code Writes data to a Page in the Intel Serial Flash.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* - Set the address within the Serial Flash where the data is to be
|
||||
* written.
|
||||
* - Set the number of bytes to be written to the Serial Flash.
|
||||
* - Write Buffer which contains the data to be written to the Serial
|
||||
* Flash.
|
||||
*/
|
||||
WriteParam.Address = Address;
|
||||
WriteParam.NumBytes = ISF_PAGE_SIZE;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
|
||||
/*
|
||||
* Prepare the write buffer. Fill in the data need to be written into
|
||||
* Serial Flash.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write operation.
|
||||
*/
|
||||
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following code Reads data from a Page in the Intel Serial Flash.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ISF_PAGE_SIZE;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
|
||||
/*
|
||||
* Perform the read operation.
|
||||
*/
|
||||
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the data read against the data Written.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
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 Serial Flash and
|
||||
* waits till the WIP bit of the Status Register becomes 0.
|
||||
*
|
||||
******************************************************************************/
|
||||
int IsfWaitForFlashNotBusy(void)
|
||||
{
|
||||
int Status;
|
||||
u8 StatusReg;
|
||||
|
||||
while(1) {
|
||||
|
||||
/*
|
||||
* Get the Status Register.
|
||||
*/
|
||||
Status = XIsf_GetStatus(&Isf, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the flash is ready to accept the next command.
|
||||
*/
|
||||
StatusReg = ReadBuffer[BYTE2];
|
||||
if((StatusReg & XISF_SR_IS_READY_MASK) == 0) {
|
||||
|
||||
/*
|
||||
* If there were errors return XST_FAILURE.
|
||||
*/
|
||||
if (StatusReg & (XISF_SR_PROG_FAIL_MASK |
|
||||
XISF_SR_ERASE_FAIL_MASK)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,655 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
* XILINX 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 xilisf_intel_read_write_example.c
|
||||
*
|
||||
* This file contains a design example using the Xilinx In-system and Serial
|
||||
* Flash Library (XilIsf). This example shows the Sector Protection Register
|
||||
* Read, Sector Protection Register Write, Sector Erase, Read and Write features.
|
||||
*
|
||||
* This example
|
||||
* - Disables the Sector Protection for all the Sectors
|
||||
* - Erases a Sector
|
||||
* - Writes to a Page within the Erased Sector
|
||||
* - Reads back the Page that is written and compares the data.
|
||||
*
|
||||
* This example has been tested with Intel (Numonyx) Serial Flash Memory (S33)
|
||||
* on a S3A-DSP starter kit. For further details about the S33 Flash device refer
|
||||
* to the Intel (Numonyx) Serial Flash Memory (S33) Data sheets.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -----------------------------------------------
|
||||
* 1.00a sdm 03/17/08 First release
|
||||
* 2.00a ktn 11/22/09 Updated to use HAL processor APIs.
|
||||
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
|
||||
* instead of driver handler.
|
||||
*
|
||||
* </pre>
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h" /* EDK generated parameters */
|
||||
#include "xintc.h" /* Interrupt controller device driver */
|
||||
#include <xilisf.h> /* Serial Flash Library header file */
|
||||
#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 ISF_SPI_SELECT 0x01
|
||||
|
||||
/*
|
||||
* Number of bytes per page in the flash device.
|
||||
*/
|
||||
#define ISF_PAGE_SIZE 256
|
||||
|
||||
/*
|
||||
* Address of the page to perform Erase, Write and Read operations.
|
||||
*/
|
||||
#define ISF_TEST_ADDRESS 0x010000;
|
||||
#define ISF_TEST_BYTE 0x20 /* Test Byte offset value written */
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
static int IsfWaitForFlashNotBusy(void);
|
||||
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 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 XIsf Isf;
|
||||
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; /* State of Spi Transfer */
|
||||
static int ErrorCount; /* Errors occurred during Spi transfers */
|
||||
|
||||
/*
|
||||
* The user needs to allocate a buffer to be used by the In-system and Serial
|
||||
* Flash Library to perform any read/write operations on the Serial Flash
|
||||
* device.
|
||||
* User applications must pass the address of this memory to the Library in
|
||||
* Serial Flash Initialization function, for the Library to work.
|
||||
* For Write operations:
|
||||
* - The size of this buffer should be equal to the Number of bytes to be
|
||||
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
|
||||
* - The size of this buffer should be large enough for usage across all the
|
||||
* applications that use a common instance of the Serial Flash.
|
||||
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
|
||||
* to the Serial Flash, through a single Write operation.
|
||||
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
|
||||
* application only reads from the Serial Flash (no write operations).
|
||||
*/
|
||||
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
|
||||
|
||||
/*
|
||||
* Buffers used during read and write transactions.
|
||||
*/
|
||||
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; /* Read Buffer */
|
||||
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
|
||||
|
||||
/************************** Function Definitions ******************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to execute the Intel Serial Flash Read/Write example.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
******************************************************************************/
|
||||
int main()
|
||||
{
|
||||
int Status;
|
||||
u32 Index;
|
||||
u32 Address;
|
||||
XIsf_WriteParam WriteParam;
|
||||
XIsf_ReadParam ReadParam;
|
||||
|
||||
/*
|
||||
* Initialize the SPI driver so that it's ready to use,
|
||||
* specify the device ID that is generated in xparameters.h.
|
||||
*/
|
||||
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
|
||||
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.
|
||||
*/
|
||||
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
|
||||
|
||||
/*
|
||||
* Start the SPI driver so that interrupts and the device are enabled.
|
||||
*/
|
||||
XSpi_Start(&Spi);
|
||||
|
||||
/*
|
||||
* Initialize the In-system and Serial Flash Library.
|
||||
*/
|
||||
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set The transfer Mode to Interrupt
|
||||
*/
|
||||
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
|
||||
|
||||
/*
|
||||
* The following code Disables the Sector Protection for all the Blocks
|
||||
* in the Intel Serial Flash.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is Not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the Sector Protection Register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear all the Block protection bits in the Sector Protection
|
||||
* Register.
|
||||
*/
|
||||
WriteBuffer[BYTE1] = ReadBuffer[BYTE2] &
|
||||
(~(XISF_SR_BLOCK_PROTECT_MASK));
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Specify the address in the Serial Flash for the Erase/Write/Read
|
||||
* operations.
|
||||
*/
|
||||
Address = ISF_TEST_ADDRESS;
|
||||
|
||||
|
||||
/*
|
||||
* The following code Erases a Sector in the Intel Serial Flash.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Sector Erase operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The following code Writes data to a Page in the Intel Serial Flash.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* - Set the address within the Serial Flash where the data is to be
|
||||
* written.
|
||||
* - Set the number of bytes to be written to the Serial Flash.
|
||||
* - Write Buffer which contains the data to be written to the Serial
|
||||
* Flash.
|
||||
*/
|
||||
WriteParam.Address = Address;
|
||||
WriteParam.NumBytes = ISF_PAGE_SIZE;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
|
||||
/*
|
||||
* Prepare the write buffer. Fill in the data need to be written into
|
||||
* Serial Flash.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following code Reads data from a Page in the Intel Serial Flash.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ISF_PAGE_SIZE;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
|
||||
/*
|
||||
* Perform the read operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the data read against the data Written.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
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 Serial Flash and
|
||||
* waits till the WIP bit of the Status Register becomes 0.
|
||||
*
|
||||
******************************************************************************/
|
||||
int IsfWaitForFlashNotBusy(void)
|
||||
{
|
||||
int Status;
|
||||
u8 StatusReg;
|
||||
|
||||
while(1) {
|
||||
|
||||
/*
|
||||
* Get the Status Register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_GetStatus(&Isf, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is in progress.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
|
||||
/*
|
||||
* Check if there are any errors in the transaction.
|
||||
*/
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the flash is ready to accept the next command.
|
||||
*/
|
||||
StatusReg = ReadBuffer[BYTE2];
|
||||
if((StatusReg & XISF_SR_IS_READY_MASK) == 0) {
|
||||
|
||||
/*
|
||||
* If there were errors return XST_FAILURE.
|
||||
*/
|
||||
if (StatusReg & (XISF_SR_PROG_FAIL_MASK |
|
||||
XISF_SR_ERASE_FAIL_MASK)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
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, u16 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, specify real mode so that
|
||||
* the SPI can cause interrupts through 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;
|
||||
}
|
925
lib/sw_services/xilisf/examples/xilisf_intel_spr_example.c
Normal file
925
lib/sw_services/xilisf/examples/xilisf_intel_spr_example.c
Normal file
|
@ -0,0 +1,925 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
* XILINX 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 xilisf_intel_spr_example.c
|
||||
*
|
||||
* This file contains a design example using the Xilinx In-system and Serial
|
||||
* Flash Library (XilIsf). This example shows the usage of Sector Erase, Sector
|
||||
* Protection, Read and Write features.
|
||||
|
||||
* This example
|
||||
* - Disables the Sector Protection for all the Sectors
|
||||
* - Erases a Sector
|
||||
* - Writes to a Page within the erased Sector
|
||||
* - Enables the Sector Protection so that all the sectors are Write protected
|
||||
* - Erases the Sector (This should not happen as the Sectors are Write protected
|
||||
* - Reads the Status Register and checks if the Erase Fail Flag is set
|
||||
* - Clears the Status Register Fail Flags
|
||||
* - Reads back the Page that is written and compares the data.
|
||||
*
|
||||
* This example has been tested with Intel (Numonyx) Serial Flash Memory (S33)
|
||||
* on a S3A-DSP starter kit. For further details about the S33 Flash device refer
|
||||
* to the Intel (Numonyx) Serial Flash Memory (S33) Data sheets.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -----------------------------------------------
|
||||
* 1.00a sdm 03/17/08 First release
|
||||
* 2.00a ktn 11/22/09 Updated to use HAL processor APIs.
|
||||
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
|
||||
* instead of driver handler.
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h" /* EDK generated parameters */
|
||||
#include "xintc.h" /* Interrupt controller device driver */
|
||||
#include "xspi.h" /* SPI device driver */
|
||||
#include <xilisf.h> /* Serial Flash Library header file */
|
||||
#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 Serial Flash device on the SPI bus, this signal is typically
|
||||
* connected to the chip select of the device.
|
||||
*/
|
||||
#define ISF_SPI_SELECT 0x01
|
||||
|
||||
/*
|
||||
* Number of bytes per page in the Serial Flash.
|
||||
*/
|
||||
#define ISF_PAGE_SIZE 256
|
||||
|
||||
/*
|
||||
* Address of the page to perform Erase, Write and Read operations.
|
||||
*/
|
||||
#define ISF_TEST_ADDRESS 0x010000;
|
||||
#define ISF_TEST_BYTE 0x20 /* Test Byte offset value written */
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
static int IsfWaitForFlashNotBusy(void);
|
||||
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 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 XIsf Isf;
|
||||
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.
|
||||
*/
|
||||
static int ErrorCount;
|
||||
|
||||
/*
|
||||
* The user needs to allocate a buffer to be used by the In-system and Serial
|
||||
* Flash Library to perform any read/write operations on the Serial Flash
|
||||
* device.
|
||||
* User applications must pass the address of this memory to the Library in
|
||||
* Serial Flash Initialization function, for the Library to work.
|
||||
* For Write operations:
|
||||
* - The size of this buffer should be equal to the Number of bytes to be
|
||||
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
|
||||
* - The size of this buffer should be large enough for usage across all the
|
||||
* applications that use a common instance of the Serial Flash.
|
||||
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
|
||||
* to the Serial Flash, through a single Write operation.
|
||||
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
|
||||
* application only reads from the Serial Flash (no write operations).
|
||||
*/
|
||||
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
|
||||
|
||||
/*
|
||||
* Buffers used during read and write transactions.
|
||||
*/
|
||||
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
|
||||
u8 WriteBuffer[ISF_PAGE_SIZE];
|
||||
|
||||
/************************** Function Definitions ******************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to execute the Intel Serial Flash SPR example.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
******************************************************************************/
|
||||
int main()
|
||||
{
|
||||
int Status;
|
||||
u32 Index;
|
||||
u32 Address;
|
||||
u8 StatusReg;
|
||||
XIsf_WriteParam WriteParam;
|
||||
XIsf_ReadParam ReadParam;
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the SPI driver so that it's ready to use,
|
||||
* specify the device ID that is generated in xparameters.h.
|
||||
*/
|
||||
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
|
||||
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.
|
||||
*/
|
||||
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
|
||||
|
||||
/*
|
||||
* Start the SPI driver so that interrupts and the device are enabled.
|
||||
*/
|
||||
XSpi_Start(&Spi);
|
||||
|
||||
/*
|
||||
* Initialize the Serial Flash Library.
|
||||
*/
|
||||
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set The transfer Mode to Interrupt
|
||||
*/
|
||||
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the sector protection register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear all the block protection bits in the sector protection register
|
||||
* value read above.
|
||||
*/
|
||||
WriteBuffer[BYTE1] = ReadBuffer[BYTE2] &
|
||||
(~(XISF_SR_BLOCK_PROTECT_MASK));
|
||||
|
||||
/*
|
||||
* Write this value to the sector protection register to disable the
|
||||
* sector protection.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Specify the address in the Serial Flash for the Erase/Write/Read
|
||||
* operations.
|
||||
*/
|
||||
Address = ISF_TEST_ADDRESS;
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Sector Erase operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* - Set the address within the Serial Flash where the data is to be
|
||||
* written.
|
||||
* - Set the number of bytes to be written to the Serial Flash.
|
||||
* - Write Buffer which contains the data to be written to the Serial
|
||||
* Flash.
|
||||
*/
|
||||
WriteParam.Address = Address;
|
||||
WriteParam.NumBytes = ISF_PAGE_SIZE;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
|
||||
/*
|
||||
* Prepare the write buffer. Fill in the data need to be written into
|
||||
* Serial Flash.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the sector protection register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set all the block protection bits in the sector protection register
|
||||
* value read above and write it back to the sector protection register.
|
||||
*/
|
||||
WriteBuffer[BYTE1] = ReadBuffer[BYTE2] |
|
||||
(XISF_SR_BLOCK_PROTECT_MASK);
|
||||
|
||||
/*
|
||||
* Enable the sector protection.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Sector Erase operation. This should not work as writes to
|
||||
* the Serial Flash are disabled.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the Status Register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_GetStatus(&Isf, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is in progress.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
|
||||
/*
|
||||
* Check if there are any errors in the transaction.
|
||||
*/
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the erase fail flag is set in the status register. This flag
|
||||
* should be set as a sector erase operation was attempted when sector
|
||||
* protection was enabled.
|
||||
*/
|
||||
StatusReg = ReadBuffer[BYTE2];
|
||||
if((StatusReg & XISF_SR_ERASE_FAIL_MASK) == 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
/*
|
||||
* Clear the status register fail flags in the Serial Flash status
|
||||
* register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Ioctl(&Isf, XISF_IOCTL_CLEAR_SR_FAIL_FLAGS);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the Status Register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_GetStatus(&Isf, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is in progress.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
|
||||
/*
|
||||
* Check if there are any errors in the transaction.
|
||||
*/
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the erase fail flag is clear in the status register. This
|
||||
* flag should be clear as a 'Clear SR Fail Flags' command has been
|
||||
* executed.
|
||||
*/
|
||||
StatusReg = ReadBuffer[BYTE2];
|
||||
if((StatusReg & XISF_SR_ERASE_FAIL_MASK) != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the sector protection register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear all the block protection bits in the sector protection register
|
||||
* value read above and write it back to the sector protection register
|
||||
* to disable sector protection for all sectors.
|
||||
*/
|
||||
WriteBuffer[BYTE1] = ReadBuffer[BYTE2] &
|
||||
~(XISF_SR_BLOCK_PROTECT_MASK);
|
||||
|
||||
/*
|
||||
* Disable the sector protection.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following code Reads data from a Page in the Intel Serial Flash.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ISF_PAGE_SIZE;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
|
||||
/*
|
||||
* Perform the read operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the data read against the data Written.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
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 Serial Flash and
|
||||
waits till the WIP bit of the status register becomes 0.
|
||||
*
|
||||
******************************************************************************/
|
||||
int IsfWaitForFlashNotBusy(void)
|
||||
{
|
||||
int Status;
|
||||
u8 StatusReg;
|
||||
|
||||
while(1) {
|
||||
|
||||
/*
|
||||
* Get the Status Register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_GetStatus(&Isf, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is in progress.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
|
||||
/*
|
||||
* Check if there are any errors in the transaction.
|
||||
*/
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the flash is ready to accept the next command.
|
||||
* If so break.
|
||||
*/
|
||||
StatusReg = ReadBuffer[BYTE2];
|
||||
if((StatusReg & XISF_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, u16 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;
|
||||
}
|
864
lib/sw_services/xilisf/examples/xilisf_qspips_stm_intr_example.c
Normal file
864
lib/sw_services/xilisf/examples/xilisf_qspips_stm_intr_example.c
Normal file
|
@ -0,0 +1,864 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
* XILINX 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 xilisf_qspips_flash_intr_example.c
|
||||
*
|
||||
*
|
||||
* This file contains a design example using the XILISF Library in
|
||||
* interrupt mode with a serial FLASH device. This examples performs
|
||||
* some transfers in Auto mode and Manual start mode, to illustrate the modes
|
||||
* available.
|
||||
* The hardware which this example runs on, must have a serial FLASH (Numonyx
|
||||
* N25Q, Winbond W25Q, or Spansion S25FL) for it to run. This example has been
|
||||
* tested with the Numonyx Serial Flash (N25Q128).
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- --- -------- -----------------------------------------------
|
||||
* 1.00 srt 06/20/12 First release
|
||||
* 1.01 srt 04/26/13 Modified Erase function to perform Write Enable operation
|
||||
* for each sector erase.
|
||||
* 1.01 srt 08/28/13 Fixed the CR 731919, by setting the proper QSPI options.
|
||||
* 5.0 sb 08/05/14 Added support for greater than 128MB flash operations.
|
||||
*
|
||||
*</pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h" /**< EDK generated parameters */
|
||||
#include "xscugic.h" /**< Interrupt controller device driver */
|
||||
#include "xil_exception.h"
|
||||
#include "xil_printf.h"
|
||||
#include <xilisf.h> /**< Serial Flash Library header file */
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
/** @name Device ID's
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
/*
|
||||
* 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 QSPI_DEVICE_ID XPAR_XQSPIPS_0_DEVICE_ID
|
||||
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
|
||||
#define QSPI_INTR_ID XPAR_XQSPIPS_0_INTR
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* The following constants define the offsets within a FlashBuffer data
|
||||
* type for each kind of data. Note that the read data offset is not the
|
||||
* same as the write data because the QSPI driver is designed to allow full
|
||||
* duplex transfers such that the number of bytes received is the number
|
||||
* sent and received.
|
||||
*/
|
||||
#define DATA_OFFSET 4 /**< Start of Data for Read/Write */
|
||||
#define DUMMY_OFFSET 4 /**< Dummy byte offset for fast, dual
|
||||
and quad reads */
|
||||
#define DUMMY_SIZE 1 /**< Number of dummy bytes for fast,
|
||||
dual and quad reads */
|
||||
|
||||
/**
|
||||
* The following constants specify the page size, sector size, and number of
|
||||
* pages and sectors for the FLASH. The page size specifies a max number of
|
||||
* bytes that can be written to the FLASH with a single transfer.
|
||||
*/
|
||||
#define NUM_PAGES 0x10000 /**< Number of Pages in the flash */
|
||||
#define PAGE_SIZE 256 /**< Page Size for Read/Write Operation */
|
||||
|
||||
/**
|
||||
* Number of flash pages to be written.
|
||||
*/
|
||||
#define PAGE_COUNT 16 /**< Number of Pages for
|
||||
Read/Write Operation */
|
||||
|
||||
/**
|
||||
* Flash address to which data is to be written.
|
||||
*/
|
||||
#define TEST_ADDRESS 0x00080000 /**< Test Address in the flash */
|
||||
#define UNIQUE_VALUE 0x05 /**< Unique Value for Test */
|
||||
|
||||
/**
|
||||
* 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 FLASH.
|
||||
*/
|
||||
#define MAX_DATA PAGE_COUNT * PAGE_SIZE /**< Max Data Calculated by
|
||||
multiplying Page count and Page Size*/
|
||||
|
||||
/**
|
||||
* The following constant defines the slave select signal that is used to
|
||||
* to select the FLASH device on the QSPI bus, this signal is typically
|
||||
* connected to the chip select of the device
|
||||
*/
|
||||
#define FLASH_QSPI_SELECT 0x00
|
||||
|
||||
#define INTR_MODE 1 /**< Interrupt Mode Enable */
|
||||
|
||||
#define FAST_READ_NUM_DUMMY_BYTES 1 /**< Number Dummy Bytes for Fast Read*/
|
||||
#define DUAL_READ_NUM_DUMMY_BYTES 1 /**< Number Dummy Bytes for Dual Read */
|
||||
#define QUAD_READ_NUM_DUMMY_BYTES 1 /**< Number Dummy Bytes for Quad Read */
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
static int QspiSetupIntrSystem(XScuGic *IntcInstancePtr,
|
||||
XQspiPs *QspiInstancePtr, u16 QspiIntrId);
|
||||
|
||||
static void QspiDisableIntrSystem(XScuGic *IntcInstancePtr, u16 QspiIntrId);
|
||||
|
||||
void XilIsf_Handler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount);
|
||||
|
||||
int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount);
|
||||
int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command);
|
||||
int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command);
|
||||
int QspiFlashIntrExample(XScuGic *IntcInstancePtr, XQspiPs *QspiInstancePtr,
|
||||
u16 QspiDeviceId, u16 QspiIntrId);
|
||||
u32 SectorMask(u32 SectorSize);
|
||||
|
||||
/************************** 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 XScuGic IntcInstance;
|
||||
static XQspiPs QspiInstance;
|
||||
static XIsf Isf;
|
||||
|
||||
/**
|
||||
* 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 ErrorCount;
|
||||
|
||||
/**
|
||||
* The following variable allows a test value to be added to the values that
|
||||
* are written to the FLASH such that unique values can be generated to
|
||||
* guarantee the writes to the FLASH were successful
|
||||
*/
|
||||
int Test = 5;
|
||||
|
||||
/**
|
||||
* The following variables are used to read and write to the eeprom and they
|
||||
* are global to avoid having large buffers on the stack
|
||||
*/
|
||||
u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE];
|
||||
u8 WriteBuffer[PAGE_SIZE + DATA_OFFSET]; /**< Write Buffer */
|
||||
u8 IsfWriteBuffer[PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];/**< IsfWrite Buffer
|
||||
used in XilISF Initialization */
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The following defines are for dual flash stacked mode interface.
|
||||
*/
|
||||
#define LQSPI_CR_FAST_QUAD_READ 0x0000006B /**< Fast Quad Read output */
|
||||
#define LQSPI_CR_1_DUMMY_BYTE 0x00000100 /**< 1 Dummy Byte between
|
||||
address and return data */
|
||||
|
||||
#define DUAL_STACK_CONFIG_WRITE (XQSPIPS_LQSPI_CR_TWO_MEM_MASK | \
|
||||
LQSPI_CR_1_DUMMY_BYTE | \
|
||||
LQSPI_CR_FAST_QUAD_READ)/**< Fast Quad Read output */
|
||||
|
||||
#define DUAL_QSPI_CONFIG_WRITE (XQSPIPS_LQSPI_CR_TWO_MEM_MASK | \
|
||||
XQSPIPS_LQSPI_CR_SEP_BUS_MASK | \
|
||||
LQSPI_CR_1_DUMMY_BYTE | \
|
||||
LQSPI_CR_FAST_QUAD_READ)/**< Fast Quad Read output */
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to call the QSPI Flash example.
|
||||
*
|
||||
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
******************************************************************************/
|
||||
int main(void)
|
||||
{
|
||||
int Status;
|
||||
|
||||
xil_printf("QSPI FLASH Interrupt Example Test \r\n");
|
||||
|
||||
/*
|
||||
* Run the Qspi Interrupt example.
|
||||
*/
|
||||
Status = QspiFlashIntrExample(&IntcInstance, &QspiInstance,
|
||||
QSPI_DEVICE_ID, QSPI_INTR_ID);
|
||||
if (Status != XST_SUCCESS) {
|
||||
xil_printf("QSPI FLASH Interrupt Example Test Failed\r\n");
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
xil_printf("Successfully ran QSPI FLASH Interrupt Example Test\r\n");
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
* The purpose of this function is to illustrate how to use the XQspiPs
|
||||
* device driver in interrupt mode. This function writes and reads data
|
||||
* from a serial FLASH.
|
||||
*
|
||||
* @param IntcInstancePtr is the instance of the interrupt
|
||||
* @param QspiInstancePtr is the Pointer to the qspi driver instance
|
||||
* @param QspiDeviceId is the Device ID of qspi
|
||||
* @param QspiIntrId is the interrupt ID for QSPI driver
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* This function calls other 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 QspiFlashIntrExample(XScuGic *IntcInstancePtr, XQspiPs *QspiInstancePtr,
|
||||
u16 QspiDeviceId, u16 QspiIntrId)
|
||||
{
|
||||
int Status;
|
||||
u8 *BufferPtr;
|
||||
u8 UniqueValue;
|
||||
int Count;
|
||||
int Page;
|
||||
XQspiPs_Config *ConfigPtr; /* Pointer to Configuration ROM data */
|
||||
u32 Options;
|
||||
|
||||
/*
|
||||
* Lookup the device configuration in the temporary CROM table. Use this
|
||||
* configuration info down below when initializing this component.
|
||||
*/
|
||||
ConfigPtr = XQspiPs_LookupConfig(QspiDeviceId);
|
||||
if (ConfigPtr == NULL) {
|
||||
return XST_DEVICE_NOT_FOUND;
|
||||
}
|
||||
|
||||
Status = XQspiPs_CfgInitialize(QspiInstancePtr, ConfigPtr,
|
||||
ConfigPtr->BaseAddress);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the QSPI options
|
||||
*/
|
||||
Options = XQSPIPS_FORCE_SSELECT_OPTION |
|
||||
XQSPIPS_MANUAL_START_OPTION |
|
||||
XQSPIPS_HOLD_B_DRIVE_OPTION;
|
||||
Status = XIsf_SetSpiConfiguration(&Isf, QspiInstancePtr,
|
||||
Options, XISF_SPI_PRESCALER);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
if(ConfigPtr->ConnectionMode == XQSPIPS_CONNECTION_MODE_STACKED) {
|
||||
/*
|
||||
* Enable two flash memories, Shared bus (NOT separate bus),
|
||||
* L_PAGE selected by default
|
||||
*/
|
||||
XQspiPs_SetLqspiConfigReg(QspiInstancePtr,
|
||||
DUAL_STACK_CONFIG_WRITE);
|
||||
}
|
||||
|
||||
if(ConfigPtr->ConnectionMode == XQSPIPS_CONNECTION_MODE_PARALLEL) {
|
||||
/*
|
||||
* Enable two flash memories on separate buses
|
||||
*/
|
||||
XQspiPs_SetLqspiConfigReg(QspiInstancePtr,
|
||||
DUAL_QSPI_CONFIG_WRITE);
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the XILISF Library */
|
||||
XIsf_Initialize(&Isf, QspiInstancePtr, FLASH_QSPI_SELECT,
|
||||
IsfWriteBuffer);
|
||||
|
||||
|
||||
|
||||
XIsf_SetTransferMode(&Isf, XISF_INTERRUPT_MODE);
|
||||
|
||||
/*
|
||||
* Connect the Qspi device to the interrupt subsystem such that
|
||||
* interrupts can occur. This function is application specific
|
||||
*/
|
||||
Status = QspiSetupIntrSystem(IntcInstancePtr, QspiInstancePtr,
|
||||
QspiIntrId);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the handler for the QSPI that will be called from the
|
||||
* interrupt context when an QSPI status occurs, specify a pointer to
|
||||
* the QSPI driver instance as the callback reference so the handler is
|
||||
* able to access the instance data
|
||||
*/
|
||||
XIsf_SetStatusHandler(&Isf, QspiInstancePtr,
|
||||
(XQspiPs_StatusHandler) XilIsf_Handler);
|
||||
|
||||
/*
|
||||
* Initialize the write buffer for a pattern to write to the FLASH
|
||||
* 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 = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE;
|
||||
Count++, UniqueValue++) {
|
||||
WriteBuffer[Count] = (u8)(UniqueValue + Test);
|
||||
}
|
||||
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
|
||||
|
||||
Status = FlashErase(&Isf, TEST_ADDRESS, MAX_DATA);
|
||||
if(Status != XST_SUCCESS){
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the data in the write buffer to the serial FLASH a page at a
|
||||
* time, starting from TEST_ADDRESS
|
||||
*/
|
||||
for (Page = 0; Page < PAGE_COUNT; Page++) {
|
||||
FlashWrite(&Isf, (Page * PAGE_SIZE) + TEST_ADDRESS,
|
||||
PAGE_SIZE, XISF_WRITE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the contents of the FLASH from TEST_ADDRESS, using Normal Read
|
||||
* command
|
||||
*/
|
||||
FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_READ);
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
|
||||
Count++, UniqueValue++) {
|
||||
|
||||
if (BufferPtr[Count] != (u8)(UniqueValue + Test)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read the contents of the FLASH from TEST_ADDRESS, using Fast Read
|
||||
* command
|
||||
*/
|
||||
|
||||
Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_FAST_READ);
|
||||
if(Status != XST_SUCCESS){
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
|
||||
Count++, UniqueValue++) {
|
||||
|
||||
if (BufferPtr[Count] != (u8)(UniqueValue + Test)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read the contents of the FLASH from TEST_ADDRESS, using DUAL IO
|
||||
* Fast Read command
|
||||
*/
|
||||
Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_DUAL_OP_FAST_READ);
|
||||
if(Status != XST_SUCCESS){
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
|
||||
Count++, UniqueValue++) {
|
||||
|
||||
if (BufferPtr[Count] != (u8)(UniqueValue + Test)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read the contents of the FLASH from TEST_ADDRESS, using QUAD OP
|
||||
* Fast Read command
|
||||
*/
|
||||
Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_QUAD_OP_FAST_READ);
|
||||
if(Status != XST_SUCCESS){
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
|
||||
Count++, UniqueValue++) {
|
||||
if (BufferPtr[Count] != (u8)(UniqueValue + Test)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
QspiDisableIntrSystem(IntcInstancePtr, QspiIntrId);
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function is the handler which performs processing for the QSPI 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 QSPI data
|
||||
* completes or an error occurs.
|
||||
*
|
||||
* This handler provides an example of how to handle QSPI interrupts but is
|
||||
* application specific.
|
||||
*
|
||||
* @param CallBackRef is a reference passed to the handler.
|
||||
* @param StatusEvent is the status of the QSPI .
|
||||
* @param ByteCount is the number of bytes transferred.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
void XilIsf_Handler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount)
|
||||
{
|
||||
/*
|
||||
* Indicate the transfer on the QSPI 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 writes to the serial FLASH connected to the QSPI interface.
|
||||
* The FLASH contains a 256 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
|
||||
* 256 byte boundaries.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf component to use.
|
||||
* @param Address contains the address to write data to in the FLASH.
|
||||
* @param ByteCount contains the number of bytes to write.
|
||||
* @param Command is the command used to write data to the flash.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command)
|
||||
{
|
||||
XIsf_WriteParam WriteParam;
|
||||
|
||||
int Status;
|
||||
|
||||
WriteParam.Address = Address;
|
||||
WriteParam.NumBytes = ByteCount;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
/*
|
||||
* Perform the Write operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Write(&Isf, Command, (void*) &WriteParam);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function reads from the serial FLASH connected to the
|
||||
* QSPI interface.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf component to use.
|
||||
* @param Address contains the address to read data from in the FLASH.
|
||||
* @param ByteCount contains the number of bytes to read.
|
||||
* @param Command is the command used to read data from the flash.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command)
|
||||
{
|
||||
XIsf_ReadParam ReadParam;
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ByteCount;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
if(Command == XISF_FAST_READ){
|
||||
ReadParam.NumDummyBytes = FAST_READ_NUM_DUMMY_BYTES;
|
||||
}
|
||||
else if(Command == XISF_DUAL_OP_FAST_READ){
|
||||
ReadParam.NumDummyBytes = DUAL_READ_NUM_DUMMY_BYTES;
|
||||
}
|
||||
else{
|
||||
ReadParam.NumDummyBytes = QUAD_READ_NUM_DUMMY_BYTES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Read operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Read(&Isf, Command, (void*) &ReadParam);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function erases the sectors in the serial FLASH connected to the
|
||||
* QSPI interface.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf component to use.
|
||||
* @param Address contains the address of the first sector which needs to
|
||||
* be erased.
|
||||
* @param ByteCount contains the total size to be erased.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount)
|
||||
{
|
||||
int Status;
|
||||
int Sector;
|
||||
u32 NumSect;
|
||||
u32 SectorSize;
|
||||
u32 NumSectors;
|
||||
u32 Sector_Mask;
|
||||
|
||||
SectorSize = Isf.SectorSize;
|
||||
NumSectors = Isf.NumSectors;
|
||||
|
||||
/* Get the sector mask value */
|
||||
Sector_Mask = SectorMask(SectorSize);
|
||||
|
||||
/*
|
||||
* If erase size is same as the total size of the flash, use bulk erase
|
||||
* command
|
||||
*/
|
||||
if (ByteCount == (NumSectors * SectorSize)) {
|
||||
|
||||
/*
|
||||
* Perform the Bulk Erase operation.
|
||||
*/
|
||||
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Erase(InstancePtr, XISF_BULK_ERASE, Address);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate no. of sectors to erase based on byte count
|
||||
*/
|
||||
NumSect = ByteCount/SectorSize + 1;
|
||||
|
||||
/*
|
||||
* If ByteCount to k sectors,
|
||||
* but the address range spans from N to N+k+1 sectors, then
|
||||
* increment no. of sectors to be erased
|
||||
*/
|
||||
|
||||
if( ((Address + ByteCount) & Sector_Mask) ==
|
||||
((Address + (NumSect * SectorSize)) &
|
||||
Sector_Mask) ) {
|
||||
NumSect++;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the erase size is less than the total size of the flash, use
|
||||
* sector erase command
|
||||
*/
|
||||
for (Sector = 0; Sector < NumSect; Sector++) {
|
||||
|
||||
/*
|
||||
* Perform the Bulk Erase operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Erase(InstancePtr, XISF_SECTOR_ERASE, Address);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Address += SectorSize;
|
||||
}
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function setups the interrupt system for an Qspi device.
|
||||
*
|
||||
* @param IntcInstancePtr is a pointer to the instance of the Intc device.
|
||||
* @param QspiInstancePtr is a pointer to the instance of the Qspi device.
|
||||
* @param QspiIntrId is the interrupt Id for an QSPI device.
|
||||
*
|
||||
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int QspiSetupIntrSystem(XScuGic *IntcInstancePtr,
|
||||
XQspiPs *QspiInstancePtr, u16 QspiIntrId)
|
||||
{
|
||||
int Status;
|
||||
|
||||
XScuGic_Config *IntcConfig; /* Instance of the interrupt controller */
|
||||
|
||||
Xil_ExceptionInit();
|
||||
|
||||
/*
|
||||
* Initialize the interrupt controller driver so that it is ready to
|
||||
* use.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Connect the interrupt controller interrupt handler to the hardware
|
||||
* interrupt handling logic in the processor.
|
||||
*/
|
||||
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
|
||||
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
|
||||
IntcInstancePtr);
|
||||
|
||||
/*
|
||||
* 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, QspiIntrId,
|
||||
(Xil_ExceptionHandler)XQspiPs_InterruptHandler,
|
||||
(void *)QspiInstancePtr);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the interrupt for the Qspi device.
|
||||
*/
|
||||
XScuGic_Enable(IntcInstancePtr, QspiIntrId);
|
||||
|
||||
/*
|
||||
* Enable interrupts in the Processor.
|
||||
*/
|
||||
Xil_ExceptionEnable();
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function disables the interrupts that occur for the Qspi device.
|
||||
*
|
||||
* @param IntcInstancePtr is the pointer to an INTC instance.
|
||||
* @param QspiIntrId is the interrupt Id for an QSPI device.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void QspiDisableIntrSystem(XScuGic *IntcInstancePtr, u16 QspiIntrId)
|
||||
{
|
||||
/*
|
||||
* Disable the interrupt for the QSPI device.
|
||||
*/
|
||||
XScuGic_Disable(IntcInstancePtr, QspiIntrId);
|
||||
|
||||
/*
|
||||
* Disconnect and disable the interrupt for the Qspi device.
|
||||
*/
|
||||
XScuGic_Disconnect(IntcInstancePtr, QspiIntrId);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function calculates the sector mask based upon the sector size value
|
||||
*
|
||||
*
|
||||
* @param SectorSize is the size of the sector of the flash
|
||||
* available on the board.
|
||||
*
|
||||
* @return will return the sector mask after calculation.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
u32 SectorMask(u32 SectorSize){
|
||||
|
||||
u32 Mask;
|
||||
|
||||
switch(SectorSize){
|
||||
case 0x10000:
|
||||
Mask = 0xFFFF0000;
|
||||
break;
|
||||
|
||||
case 0x20000:
|
||||
Mask = 0xFFFE0000;
|
||||
break;
|
||||
|
||||
case 0x40000:
|
||||
Mask = 0xFFFC0000;
|
||||
break;
|
||||
|
||||
case 0x80000:
|
||||
Mask = 0xFFF80000;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return Mask;
|
||||
}
|
|
@ -0,0 +1,727 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
* XILINX 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 xilisf_qspips_flash_polled_example.c
|
||||
*
|
||||
*
|
||||
* This file contains a design example using the XILISF Library in
|
||||
* interrupt mode with a serial FLASH device. This examples performs
|
||||
* some transfers in Auto mode and Manual start mode, to illustrate the modes
|
||||
* available.
|
||||
* The hardware which this example runs on, must have a serial FLASH (Numonyx
|
||||
* N25Q, Winbond W25Q, or Spansion S25FL) for it to run. This example has been
|
||||
* tested with the Numonyx Serial Flash (N25Q128).
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- --- -------- -----------------------------------------------
|
||||
* 1.00 srt 06/20/12 First release
|
||||
* 1.01 srt 04/26/13 Modified Erase function to perform Write Enable operation
|
||||
* for each sector erase.
|
||||
* 1.01 srt 08/28/13 Fixed the CR 731919, by setting the proper QSPI options.
|
||||
* 5.0 sb 08/05/14 Added support for greater than 128MB flash operations.
|
||||
*</pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h" /* EDK generated parameters */
|
||||
#include "xscugic.h" /* Interrupt controller device driver */
|
||||
#include "xil_exception.h"
|
||||
#include "xil_printf.h"
|
||||
#include "xilisf.h" /* Serial Flash Library header file */
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
/** @name Device ID's
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
/*
|
||||
* 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 QSPI_DEVICE_ID XPAR_XQSPIPS_0_DEVICE_ID
|
||||
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
|
||||
#define QSPI_INTR_ID XPAR_XQSPIPS_0_INTR
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* The following constants define the offsets within a FlashBuffer data
|
||||
* type for each kind of data. Note that the read data offset is not the
|
||||
* same as the write data because the QSPI driver is designed to allow full
|
||||
* duplex transfers such that the number of bytes received is the number
|
||||
* sent and received.
|
||||
*/
|
||||
#define DATA_OFFSET 4 /**< Start of Data for Read/Write */
|
||||
#define DUMMY_OFFSET 4 /**< Dummy byte offset for fast, dual and quad
|
||||
reads */
|
||||
#define DUMMY_SIZE 1 /**< Number of dummy bytes for fast, dual and
|
||||
quad reads */
|
||||
|
||||
/**
|
||||
* The following constants specify the page size and number of
|
||||
* pages for the FLASH. The page size specifies a max number of
|
||||
* bytes that can be written to the FLASH with a single transfer.
|
||||
*/
|
||||
#define NUM_PAGES 0x10000 /**< Number of Pages in the flash */
|
||||
#define PAGE_SIZE 256 /**< Page Size for Read/Write Operation */
|
||||
|
||||
/**
|
||||
* Number of flash pages to be written.
|
||||
*/
|
||||
#define PAGE_COUNT 32 /**< Number of Pages for r/w Operation */
|
||||
|
||||
/**
|
||||
* Flash address to which data is ot be written.
|
||||
*/
|
||||
#define TEST_ADDRESS 0x00090000 /**< Test Address in the flash */
|
||||
#define UNIQUE_VALUE 0x08 /**< Unique Value for Test */
|
||||
|
||||
|
||||
/**
|
||||
* 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 FLASH.
|
||||
*/
|
||||
#define MAX_DATA PAGE_COUNT * PAGE_SIZE /**< Max Data Calculated by
|
||||
multiplying Page count and Page Size */
|
||||
|
||||
/**
|
||||
* The following constant defines the slave select signal that is used to
|
||||
* to select the FLASH device on the QSPI bus, this signal is typically
|
||||
* connected to the chip select of the device
|
||||
*/
|
||||
#define FLASH_QSPI_SELECT 0x00 /**< Interrupt Mode Enable */
|
||||
|
||||
#define FAST_READ_NUM_DUMMY_BYTES 1 /**< Number Dummy Bytes for
|
||||
Fast Read */
|
||||
#define DUAL_READ_NUM_DUMMY_BYTES 1 /**< Number Dummy Bytes for
|
||||
Dual Read */
|
||||
#define QUAD_READ_NUM_DUMMY_BYTES 1 /**< Number Dummy Bytes for
|
||||
Quad Read */
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount);
|
||||
int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount,
|
||||
u8 Command);
|
||||
int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount,
|
||||
u8 Command);
|
||||
int QspiFlashPollExample(XScuGic *IntcInstancePtr, XQspiPs *QspiInstancePtr,
|
||||
u16 QspiDeviceId, u16 QspiIntrId);
|
||||
static u32 SectorMask(u32 SectorSize);
|
||||
|
||||
/************************** 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 XScuGic IntcInstance;
|
||||
static XQspiPs QspiInstance;
|
||||
static XIsf Isf;
|
||||
static XQspiPs_Config *ConfigPtr; /**< Pointer to Configuration ROM data */
|
||||
|
||||
/**
|
||||
* The following variables are shared between non-interrupt processing and
|
||||
* interrupt processing such that they must be global.
|
||||
*/
|
||||
volatile int TransferInProgress;
|
||||
|
||||
/**
|
||||
* The following variable allows a test value to be added to the values that
|
||||
* are written to the FLASH such that unique values can be generated to
|
||||
* guarantee the writes to the FLASH were successful
|
||||
*/
|
||||
int Test_Polled = 7;
|
||||
|
||||
/**
|
||||
* The following variables are used to read and write to the eeprom and they
|
||||
* are global to avoid having large buffers on the stack
|
||||
*/
|
||||
u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE];
|
||||
u8 WriteBuffer[PAGE_SIZE + DATA_OFFSET]; /**< Write Buffer */
|
||||
u8 IsfWriteBuffer[PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];/**< IsfWrite Buffer
|
||||
used in XilISF Initialization */
|
||||
|
||||
/**
|
||||
* The following defines are for dual flash stacked mode interface.
|
||||
*/
|
||||
#define LQSPI_CR_FAST_QUAD_READ 0x0000006B /**< Fast Quad Read output */
|
||||
#define LQSPI_CR_1_DUMMY_BYTE 0x00000100 /**< 1 Dummy Byte between
|
||||
address and return data */
|
||||
|
||||
#define DUAL_STACK_CONFIG_WRITE (XQSPIPS_LQSPI_CR_TWO_MEM_MASK | \
|
||||
LQSPI_CR_1_DUMMY_BYTE | \
|
||||
LQSPI_CR_FAST_QUAD_READ) /**< Fast Quad Read output */
|
||||
|
||||
#define DUAL_QSPI_CONFIG_WRITE (XQSPIPS_LQSPI_CR_TWO_MEM_MASK | \
|
||||
XQSPIPS_LQSPI_CR_SEP_BUS_MASK | \
|
||||
LQSPI_CR_1_DUMMY_BYTE | \
|
||||
LQSPI_CR_FAST_QUAD_READ) /**< Fast Quad Read output */
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to call the QSPI Flash example.
|
||||
*
|
||||
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
******************************************************************************/
|
||||
int main(void)
|
||||
{
|
||||
int Status;
|
||||
|
||||
xil_printf("QSPI FLASH Polling Example Test \r\n");
|
||||
|
||||
/*
|
||||
* Run the Qspi Interrupt example.
|
||||
*/
|
||||
Status = QspiFlashPollExample(&IntcInstance, &QspiInstance,
|
||||
QSPI_DEVICE_ID, QSPI_INTR_ID);
|
||||
if (Status != XST_SUCCESS) {
|
||||
xil_printf("QSPI FLASH Polling Example Test Failed\r\n");
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
xil_printf("Successfully ran QSPI FLASH Polling Example Test\r\n");
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
* The purpose of this function is to illustrate how to use the XQspiPs
|
||||
* device driver in interrupt mode. This function writes and reads data
|
||||
* from a serial FLASH.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* This function calls other 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 QspiFlashPollExample(XScuGic *IntcInstancePtr, XQspiPs *QspiInstancePtr,
|
||||
u16 QspiDeviceId, u16 QspiIntrId)
|
||||
{
|
||||
u8 *BufferPtr;
|
||||
u8 UniqueValue;
|
||||
int Count;
|
||||
int Page;
|
||||
int Status;
|
||||
u32 Options;
|
||||
|
||||
/*
|
||||
* Lookup the device configuration in the temporary CROM table. Use this
|
||||
* configuration info down below when initializing this component.
|
||||
*/
|
||||
ConfigPtr = XQspiPs_LookupConfig(QspiDeviceId);
|
||||
if (ConfigPtr == NULL) {
|
||||
return XST_DEVICE_NOT_FOUND;
|
||||
}
|
||||
|
||||
Status = XQspiPs_CfgInitialize(QspiInstancePtr, ConfigPtr,
|
||||
ConfigPtr->BaseAddress);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the QSPI options
|
||||
*/
|
||||
Options = XQSPIPS_FORCE_SSELECT_OPTION |
|
||||
XQSPIPS_MANUAL_START_OPTION |
|
||||
XQSPIPS_HOLD_B_DRIVE_OPTION;
|
||||
XIsf_SetSpiConfiguration(&Isf, QspiInstancePtr, Options,
|
||||
XISF_SPI_PRESCALER);
|
||||
|
||||
if(ConfigPtr->ConnectionMode == XQSPIPS_CONNECTION_MODE_STACKED) {
|
||||
/*
|
||||
* Enable two flash memories, Shared bus
|
||||
* (NOT separate bus), L_PAGE selected by default
|
||||
*/
|
||||
XQspiPs_SetLqspiConfigReg(QspiInstancePtr,
|
||||
DUAL_STACK_CONFIG_WRITE);
|
||||
}
|
||||
|
||||
if(ConfigPtr->ConnectionMode == XQSPIPS_CONNECTION_MODE_PARALLEL) {
|
||||
/*
|
||||
* Enable two flash memories on separate buses
|
||||
*/
|
||||
XQspiPs_SetLqspiConfigReg(QspiInstancePtr,
|
||||
DUAL_QSPI_CONFIG_WRITE);
|
||||
}
|
||||
|
||||
/* Initialize the XILISF Library */
|
||||
XIsf_Initialize(&Isf, QspiInstancePtr, FLASH_QSPI_SELECT,
|
||||
IsfWriteBuffer);
|
||||
|
||||
/*
|
||||
* Initialize the write buffer for a pattern to write to the FLASH
|
||||
* 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 = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE;
|
||||
Count++, UniqueValue++) {
|
||||
WriteBuffer[Count] = (u8)(UniqueValue + Test_Polled);
|
||||
}
|
||||
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
|
||||
|
||||
|
||||
Status = FlashErase(&Isf, TEST_ADDRESS, MAX_DATA);
|
||||
if(Status != XST_SUCCESS){
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the data in the write buffer to the serial FLASH a page at a
|
||||
* time, starting from TEST_ADDRESS
|
||||
*/
|
||||
|
||||
for (Page = 0; Page < PAGE_COUNT; Page++) {
|
||||
Status = FlashWrite(&Isf,
|
||||
(Page * PAGE_SIZE) + TEST_ADDRESS, PAGE_SIZE,
|
||||
XISF_QUAD_IP_PAGE_WRITE);
|
||||
if(Status != XST_SUCCESS){
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
**********************NORMAL READ*********************
|
||||
******************************************************/
|
||||
|
||||
/*
|
||||
* Read the contents of the FLASH from TEST_ADDRESS, using Normal Read
|
||||
* command
|
||||
*/
|
||||
Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_READ);
|
||||
if(Status != XST_SUCCESS){
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
|
||||
Count++, UniqueValue++) {
|
||||
if (BufferPtr[Count] != (u8)(UniqueValue + Test_Polled)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************
|
||||
**********************FAST READ***********************
|
||||
******************************************************/
|
||||
|
||||
/*
|
||||
* Read the contents of the FLASH from TEST_ADDRESS, using Fast Read
|
||||
* command
|
||||
*/
|
||||
Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA,
|
||||
XISF_FAST_READ);
|
||||
if(Status != XST_SUCCESS){
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
|
||||
Count++, UniqueValue++) {
|
||||
if (BufferPtr[Count] != (u8)(UniqueValue + Test_Polled)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************
|
||||
******************DUAL OP FAST READ*******************
|
||||
******************************************************/
|
||||
|
||||
/*
|
||||
* Read the contents of the FLASH from TEST_ADDRESS, using DUAL OP
|
||||
* Fast Read command
|
||||
*/
|
||||
Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA,
|
||||
XISF_DUAL_OP_FAST_READ);
|
||||
if(Status != XST_SUCCESS){
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
|
||||
Count++, UniqueValue++) {
|
||||
|
||||
if (BufferPtr[Count] != (u8)(UniqueValue + Test_Polled)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
******************QUAD IO FAST READ*******************
|
||||
******************************************************/
|
||||
|
||||
/*
|
||||
* Read the contents of the FLASH from TEST_ADDRESS, using QUAD IO
|
||||
* Fast Read command
|
||||
*/
|
||||
Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA,
|
||||
XISF_QUAD_OP_FAST_READ);
|
||||
if(Status != XST_SUCCESS){
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
|
||||
Count++, UniqueValue++) {
|
||||
if (BufferPtr[Count] != (u8)(UniqueValue + Test_Polled)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function writes to the serial FLASH connected to the QSPI interface.
|
||||
* The FLASH contains a 256 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
|
||||
* 256 byte boundaries.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf component to use.
|
||||
* @param Address contains the address to write data to in the FLASH.
|
||||
* @param ByteCount contains the number of bytes to write.
|
||||
* @param Command is the command used to write data to the flash.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount,
|
||||
u8 Command)
|
||||
{
|
||||
XIsf_WriteParam WriteParam;
|
||||
|
||||
int Status;
|
||||
|
||||
WriteParam.Address = Address;
|
||||
WriteParam.NumBytes = ByteCount;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
|
||||
/*
|
||||
* Perform the Write operation.
|
||||
*/
|
||||
Status = XIsf_Write(&Isf, Command, (void*) &WriteParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function reads from the serial FLASH connected to the
|
||||
* QSPI interface.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf component to use.
|
||||
* @param Address contains the address to read data from in the FLASH.
|
||||
* @param ByteCount contains the number of bytes to read.
|
||||
* @param Command is the command used to read data from the flash.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command)
|
||||
{
|
||||
XIsf_ReadParam ReadParam;
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes ReadParam.NumDummyBytesto be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ByteCount;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
if(Command == XISF_FAST_READ){
|
||||
ReadParam.NumDummyBytes = FAST_READ_NUM_DUMMY_BYTES;
|
||||
}
|
||||
else if(Command == XISF_DUAL_OP_FAST_READ){
|
||||
ReadParam.NumDummyBytes = DUAL_READ_NUM_DUMMY_BYTES;
|
||||
}
|
||||
else{
|
||||
ReadParam.NumDummyBytes = QUAD_READ_NUM_DUMMY_BYTES;
|
||||
}
|
||||
/*
|
||||
* Perform the Read operation.
|
||||
*/
|
||||
Status = XIsf_Read(&Isf, Command, (void*) &ReadParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function erases the sectors in the serial FLASH connected to the
|
||||
* QSPI interface.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf component to use.
|
||||
* @param Address contains the address of the first sector which needs to
|
||||
* be erased.
|
||||
* @param ByteCount contains the total size to be erased.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount)
|
||||
{
|
||||
int Status;
|
||||
int Sector;
|
||||
u32 LqspiCr;
|
||||
u32 NumSect;
|
||||
u32 SectorSize;
|
||||
u32 NumSectors;
|
||||
u32 Sector_Mask;
|
||||
/*
|
||||
* Get the value of Sector Size and Number of Sectors for the flash
|
||||
*/
|
||||
SectorSize = Isf.SectorSize;
|
||||
NumSectors = Isf.NumSectors;
|
||||
|
||||
/* Get the sector mask value */
|
||||
Sector_Mask = SectorMask(SectorSize);
|
||||
|
||||
/*
|
||||
* If erase size is same as the total size of the flash, use bulk erase
|
||||
* command
|
||||
*/
|
||||
if (ByteCount == (NumSectors * SectorSize)) {
|
||||
|
||||
#ifdef XPAR_XQSPIPS_0_DEVICE_ID
|
||||
if(ConfigPtr->ConnectionMode ==
|
||||
XQSPIPS_CONNECTION_MODE_STACKED){
|
||||
|
||||
/*
|
||||
* Get the current LQSPI configuration register value
|
||||
*/
|
||||
LqspiCr =
|
||||
XQspiPs_GetLqspiConfigReg(InstancePtr->SpiInstPtr);
|
||||
/*
|
||||
* Set selection to L_PAGE
|
||||
*/
|
||||
XQspiPs_SetLqspiConfigReg(InstancePtr->SpiInstPtr,
|
||||
LqspiCr & (~XQSPIPS_LQSPI_CR_U_PAGE_MASK));
|
||||
|
||||
/*
|
||||
* Assert the Flash chip select.
|
||||
*/
|
||||
XQspiPs_SetSlaveSelect(InstancePtr->SpiInstPtr);
|
||||
}
|
||||
#endif /*XPAR_XQSPIPS_0_DEVICE_ID*/
|
||||
|
||||
/*
|
||||
* Call Bulk erase
|
||||
*/
|
||||
Status = XIsf_Erase(InstancePtr,
|
||||
XISF_BULK_ERASE, Address);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef XPAR_XQSPIPS_0_DEVICE_ID
|
||||
/*
|
||||
* If stacked mode, bulk erase second flash
|
||||
*/
|
||||
if(ConfigPtr->ConnectionMode ==
|
||||
XQSPIPS_CONNECTION_MODE_STACKED){
|
||||
|
||||
/*
|
||||
* Get the current LQSPI configuration register value
|
||||
*/
|
||||
LqspiCr =
|
||||
XQspiPs_GetLqspiConfigReg(InstancePtr->SpiInstPtr);
|
||||
/*
|
||||
* Set selection to U_PAGE
|
||||
*/
|
||||
XQspiPs_SetLqspiConfigReg(InstancePtr->SpiInstPtr,
|
||||
LqspiCr | XQSPIPS_LQSPI_CR_U_PAGE_MASK);
|
||||
|
||||
/*
|
||||
* Assert the Flash chip select.
|
||||
*/
|
||||
XQspiPs_SetSlaveSelect(InstancePtr->SpiInstPtr);
|
||||
|
||||
|
||||
/*
|
||||
* Call Bulk erase
|
||||
*/
|
||||
Status = XIsf_Erase(InstancePtr,
|
||||
XISF_BULK_ERASE, Address);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
#endif /*XPAR_XQSPIPS_0_DEVICE_ID*/
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate no. of sectors to erase based on byte count
|
||||
*/
|
||||
NumSect = ByteCount/SectorSize + 1;
|
||||
|
||||
/*
|
||||
* If ByteCount to k sectors,
|
||||
* but the address range spans from N to N+k+1 sectors, then
|
||||
* increment no. of sectors to be erased
|
||||
*/
|
||||
|
||||
if( ((Address + ByteCount) & Sector_Mask) ==
|
||||
((Address + (NumSect * SectorSize)) &
|
||||
Sector_Mask) ) {
|
||||
NumSect++;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the erase size is less than the total size of the flash, use
|
||||
* sector erase command
|
||||
*/
|
||||
for (Sector = 0; Sector < NumSect; Sector++) {
|
||||
|
||||
/*
|
||||
* Perform the Sector Erase operation.
|
||||
*/
|
||||
Status = XIsf_Erase(InstancePtr, XISF_SECTOR_ERASE, Address);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Address += SectorSize;
|
||||
}
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function calculates the sector mask based upon the sector size value
|
||||
*
|
||||
*
|
||||
* @param SectorSize is the size of the sector of the flash
|
||||
* available on the board.
|
||||
*
|
||||
* @return will return the sector mask after calculation.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
u32 SectorMask(u32 SectorSize){
|
||||
|
||||
u32 Mask;
|
||||
|
||||
switch(SectorSize){
|
||||
case 0x10000:
|
||||
Mask = 0xFFFF0000;
|
||||
break;
|
||||
|
||||
case 0x20000:
|
||||
Mask = 0xFFFE0000;
|
||||
break;
|
||||
case 0x40000:
|
||||
Mask = 0xFFFC0000;
|
||||
break;
|
||||
|
||||
case 0x80000:
|
||||
Mask = 0xFFF80000;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return Mask;
|
||||
}
|
717
lib/sw_services/xilisf/examples/xilisf_spips_sst_intr_example.c
Normal file
717
lib/sw_services/xilisf/examples/xilisf_spips_sst_intr_example.c
Normal file
|
@ -0,0 +1,717 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
* XILINX 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 xilisf_spips_flash_intr_example.c
|
||||
*
|
||||
*
|
||||
* This file contains a design example using the XILISF Library in
|
||||
* interrupt mode with a serial FLASH device. This examples performs
|
||||
* some transfers in Auto mode and Manual start mode, to illustrate the modes
|
||||
* available.
|
||||
* The hardware which this example runs on, must have a serial FLASH (Numonyx
|
||||
* N25Q, Winbond W25Q, SST or Spansion S25FL) for it to run. This example has
|
||||
* been tested with the SST Flash.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- --- -------- -----------------------------------------------
|
||||
* 1.00 srt 06/20/12 First release
|
||||
* 3.01 srt 03/03/13 Modified the flash write, erase and read logic.
|
||||
* Ensured flash blocks are unprotected befor a flash erase
|
||||
* or write operation. (CR 703816)
|
||||
* 3.02 srt 04/26/13 Modified Erase function to perform Write Enable operation
|
||||
* for each sector erase.
|
||||
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
|
||||
* instead of driver handler.
|
||||
*</pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h" /* EDK generated parameters */
|
||||
#include "xscugic.h" /* Interrupt controller device driver */
|
||||
#include "xil_exception.h"
|
||||
#include "xil_printf.h"
|
||||
#include <xilisf.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_XSPIPS_0_DEVICE_ID
|
||||
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
|
||||
#define SPI_INTR_ID XPAR_XSPIPS_1_INTR
|
||||
|
||||
/*
|
||||
* The following constants define the offsets within a FlashBuffer 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 DATA_OFFSET 4 /* Start of Data for Read/Write */
|
||||
#define DUMMY_SIZE 1 /* Number of dummy bytes for fast, dual and
|
||||
quad reads */
|
||||
|
||||
/*
|
||||
* The following constants specify the page size, sector size, and number of
|
||||
* pages and sectors for the FLASH. The page size specifies a max number of
|
||||
* bytes that can be written to the FLASH with a single transfer.
|
||||
*/
|
||||
#define SECTOR_SIZE 0x1000
|
||||
#define NUM_SECTORS 0x100
|
||||
|
||||
/*
|
||||
* Flash address to which data is to be written.
|
||||
*/
|
||||
#define TEST_ADDRESS 0x00
|
||||
#define UNIQUE_VALUE 0x05
|
||||
|
||||
/*
|
||||
* 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 FLASH.
|
||||
*/
|
||||
#define MAX_DATA SECTOR_SIZE * NUM_SECTORS
|
||||
|
||||
/*
|
||||
* 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 FLASH_SPI_SELECT 0x01
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
static int SpiSetupIntrSystem(XScuGic *IntcInstancePtr,
|
||||
XSpiPs *SpiInstancePtr, u16 SpiIntrId);
|
||||
|
||||
static void SpiDisableIntrSystem(XScuGic *IntcInstancePtr, u16 SpiIntrId);
|
||||
|
||||
void SpiHandler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount);
|
||||
|
||||
int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount);
|
||||
int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command);
|
||||
int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command);
|
||||
int WriteEnable(XIsf *InstancePtr);
|
||||
int SpiFlashIntrExample(XScuGic *IntcInstancePtr, XSpiPs *SpiInstancePtr,
|
||||
u16 SpiDeviceId, u16 SpiIntrId);
|
||||
|
||||
/************************** 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 XScuGic IntcInstance;
|
||||
static XSpiPs SpiInstance;
|
||||
static XIsf Isf;
|
||||
/*
|
||||
* 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 ErrorCount;
|
||||
|
||||
/*
|
||||
* The following variables are used to read and write to the eeprom and they
|
||||
* are global to avoid having large buffers on the stack
|
||||
*/
|
||||
u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE];
|
||||
u8 WriteBuffer[MAX_DATA + DATA_OFFSET];
|
||||
u8 IsfWriteBuffer[XISF_CMD_SEND_EXTRA_BYTES + 1];
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to call the SPI Flash example.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
******************************************************************************/
|
||||
int main(void)
|
||||
{
|
||||
int Status;
|
||||
|
||||
xil_printf("SPI FLASH Interrupt Example Test \r\n");
|
||||
|
||||
/*
|
||||
* Run the Spi Interrupt example.
|
||||
*/
|
||||
Status = SpiFlashIntrExample(&IntcInstance, &SpiInstance,
|
||||
SPI_DEVICE_ID, SPI_INTR_ID);
|
||||
if (Status != XST_SUCCESS) {
|
||||
xil_printf("SPI FLASH Interrupt Example Test Failed\r\n");
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
xil_printf("Successfully ran SPI FLASH Interrupt Example Test\r\n");
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* The purpose of this function is to illustrate how to use the XSpiPs
|
||||
* device driver in interrupt mode. This function writes and reads data
|
||||
* from a serial FLASH.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* This function calls other 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 SpiFlashIntrExample(XScuGic *IntcInstancePtr, XSpiPs *SpiInstancePtr,
|
||||
u16 SpiDeviceId, u16 SpiIntrId)
|
||||
{
|
||||
int Status;
|
||||
u8 *BufferPtr;
|
||||
u8 UniqueValue;
|
||||
u32 Count;
|
||||
XSpiPs_Config *ConfigPtr; /* Pointer to Configuration ROM data */
|
||||
u32 TempAddress;
|
||||
|
||||
/*
|
||||
* Lookup the device configuration in the temporary CROM table. Use this
|
||||
* configuration info down below when initializing this component.
|
||||
*/
|
||||
ConfigPtr = XSpiPs_LookupConfig(SpiDeviceId);
|
||||
if (ConfigPtr == NULL) {
|
||||
return XST_DEVICE_NOT_FOUND;
|
||||
}
|
||||
|
||||
XSpiPs_CfgInitialize(SpiInstancePtr, ConfigPtr,
|
||||
ConfigPtr->BaseAddress);
|
||||
|
||||
/* Initialize the XILISF Library */
|
||||
XIsf_Initialize(&Isf, SpiInstancePtr, FLASH_SPI_SELECT,
|
||||
IsfWriteBuffer);
|
||||
|
||||
XIsf_SetTransferMode(&Isf, XISF_INTERRUPT_MODE);
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
XIsf_SetStatusHandler(&Isf, SpiInstancePtr,
|
||||
(XSpiPs_StatusHandler) SpiHandler);
|
||||
|
||||
|
||||
memset(WriteBuffer, 0x00, sizeof(WriteBuffer));
|
||||
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
|
||||
|
||||
/* Unprotect Sectors */
|
||||
FlashWrite(&Isf, 0, 0, XISF_WRITE_STATUS_REG);
|
||||
|
||||
FlashErase(&Isf, TEST_ADDRESS, MAX_DATA);
|
||||
|
||||
/*
|
||||
* Initialize the write buffer for a pattern to write to the FLASH
|
||||
* 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
|
||||
*/
|
||||
TempAddress = TEST_ADDRESS;
|
||||
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
|
||||
Count++, UniqueValue++, TempAddress++) {
|
||||
WriteBuffer[0] = (u8)(UniqueValue);
|
||||
FlashWrite(&Isf, TempAddress, 1, XISF_WRITE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the contents of the FLASH from TEST_ADDRESS, using Normal Read
|
||||
* command
|
||||
*/
|
||||
FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_READ);
|
||||
|
||||
/*
|
||||
* 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[DATA_OFFSET];
|
||||
|
||||
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
|
||||
Count++, UniqueValue++) {
|
||||
if (BufferPtr[Count] != (u8)(UniqueValue)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
SpiDisableIntrSystem(IntcInstancePtr, SpiIntrId);
|
||||
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 Serial Flash and
|
||||
waits till the WIP bit of the status register becomes 0.
|
||||
*
|
||||
******************************************************************************/
|
||||
int IsfWaitForFlashNotBusy(void)
|
||||
{
|
||||
int Status;
|
||||
u8 StatusReg;
|
||||
|
||||
while(1) {
|
||||
|
||||
/*
|
||||
* Get the Status Register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_GetStatus(&Isf, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is in progress.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
|
||||
/*
|
||||
* Check if there are any errors in the transaction.
|
||||
*/
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the flash is ready to accept the next command.
|
||||
* If so break.
|
||||
*/
|
||||
StatusReg = ReadBuffer[BYTE2];
|
||||
if((StatusReg & XISF_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 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) {
|
||||
ErrorCount++;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*
|
||||
* This function writes to the serial FLASH connected to the SPI interface.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf component to use.
|
||||
* @param Address contains the address to write data to in the FLASH.
|
||||
* @param ByteCount contains the number of bytes to write.
|
||||
* @param Command is the command used to write data to the flash. SPI
|
||||
* device supports Byte Program command to write data to the
|
||||
* flash.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command)
|
||||
{
|
||||
XIsf_WriteParam WriteParam;
|
||||
|
||||
int Status;
|
||||
|
||||
WriteEnable(InstancePtr);
|
||||
|
||||
WriteParam.Address = Address;
|
||||
WriteParam.NumBytes = ByteCount;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
/*
|
||||
* Perform the Write operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Write(&Isf, Command, (void*) &WriteParam);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This function reads from the serial FLASH connected to the
|
||||
* SPI interface.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf component to use.
|
||||
* @param Address contains the address to read data from in the FLASH.
|
||||
* @param ByteCount contains the number of bytes to read.
|
||||
* @param Command is the command used to read data from the flash. SPI
|
||||
* device supports one of the Read, Fast Read, Dual Read and Fast
|
||||
* Read commands to read data from the flash.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command)
|
||||
{
|
||||
XIsf_ReadParam ReadParam;
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ByteCount;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
|
||||
/*
|
||||
* Perform the Read operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Read(&Isf, Command, (void*) &ReadParam);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*
|
||||
* This function erases the sectors in the serial FLASH connected to the SPI
|
||||
* interface.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf component to use.
|
||||
* @param Address contains the address of the first sector which needs to
|
||||
* be erased.
|
||||
* @param ByteCount contains the total size to be erased.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount)
|
||||
{
|
||||
int Status;
|
||||
int Sector;
|
||||
|
||||
/*
|
||||
* If the erase size is less than the total size of the flash, use
|
||||
* sector erase command
|
||||
*/
|
||||
for (Sector = 0; Sector < ((ByteCount / SECTOR_SIZE) + 1); Sector++) {
|
||||
|
||||
/*
|
||||
* Write enable instruction has to be executed prior to
|
||||
* any Write operation.
|
||||
*/
|
||||
WriteEnable(InstancePtr);
|
||||
|
||||
/*
|
||||
* Perform the Sector Erase operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Erase(InstancePtr, XISF_SECTOR_ERASE, Address);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Address += SECTOR_SIZE;
|
||||
}
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function performs the write enable operation.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
int WriteEnable(XIsf *InstancePtr)
|
||||
{
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function setups the interrupt system for an Spi device.
|
||||
*
|
||||
* @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 for an SPI device.
|
||||
*
|
||||
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int SpiSetupIntrSystem(XScuGic *IntcInstancePtr,
|
||||
XSpiPs *SpiInstancePtr, u16 SpiIntrId)
|
||||
{
|
||||
int Status;
|
||||
|
||||
XScuGic_Config *IntcConfig; /* Instance of the interrupt controller */
|
||||
|
||||
Xil_ExceptionInit();
|
||||
|
||||
/*
|
||||
* Initialize the interrupt controller driver so that it is ready to
|
||||
* use.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Connect the interrupt controller interrupt handler to the hardware
|
||||
* interrupt handling logic in the processor.
|
||||
*/
|
||||
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
|
||||
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
|
||||
IntcInstancePtr);
|
||||
|
||||
/*
|
||||
* 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_ExceptionHandler)XSpiPs_InterruptHandler,
|
||||
(void *)SpiInstancePtr);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the interrupt for the Spi device.
|
||||
*/
|
||||
XScuGic_Enable(IntcInstancePtr, SpiIntrId);
|
||||
|
||||
/*
|
||||
* Enable interrupts in the Processor.
|
||||
*/
|
||||
Xil_ExceptionEnable();
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function disables the interrupts that occur for the Spi device.
|
||||
*
|
||||
* @param IntcInstancePtr is the pointer to an INTC instance.
|
||||
* @param SpiIntrId is the interrupt Id for an SPI device.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void SpiDisableIntrSystem(XScuGic *IntcInstancePtr, u16 SpiIntrId)
|
||||
{
|
||||
/*
|
||||
* Disable the interrupt for the SPI device.
|
||||
*/
|
||||
XScuGic_Disable(IntcInstancePtr, SpiIntrId);
|
||||
|
||||
/*
|
||||
* Disconnect and disable the interrupt for the Spi device.
|
||||
*/
|
||||
XScuGic_Disconnect(IntcInstancePtr, SpiIntrId);
|
||||
}
|
|
@ -0,0 +1,480 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
* XILINX 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 xilisf_spips_flash_polled_example.c
|
||||
*
|
||||
* This file contains a design example using the XILISF Library in
|
||||
* interrupt mode with a serial FLASH device. This examples performs
|
||||
* some transfers in Auto mode and Manual start mode, to illustrate the modes
|
||||
* available.
|
||||
* The hardware which this example runs on, must have a serial FLASH (Numonyx
|
||||
* N25Q, Winbond W25Q, SST or Spansion S25FL) for it to run. This example has
|
||||
* been tested with the SST Flash.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- --- -------- -----------------------------------------------
|
||||
* 1.00 srt 06/20/12 First release
|
||||
* 3.01 srt 03/03/13 Modified the flash write, erase and read logic.
|
||||
* Ensured flash blocks are unprotected befor a flash erase
|
||||
* or write operation. (CR 703816)
|
||||
* 3.02 srt 04/26/13 Modified Erase function to perform Write Enable operation
|
||||
* for each sector erase.
|
||||
*
|
||||
*</pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h" /* EDK generated parameters */
|
||||
#include "xscugic.h" /* Interrupt controller device driver */
|
||||
#include "xil_exception.h"
|
||||
#include "xil_printf.h"
|
||||
#include <xilisf.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_XSPIPS_0_DEVICE_ID
|
||||
|
||||
/*
|
||||
* The following constants define the offsets within a FlashBuffer 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 DATA_OFFSET 4 /* Start of Data for Read/Write */
|
||||
#define DUMMY_SIZE 1 /* Number of dummy bytes for fast, dual and
|
||||
quad reads */
|
||||
|
||||
/*
|
||||
* The following constants specify the page size, sector size, and number of
|
||||
* pages and sectors for the FLASH. The page size specifies a max number of
|
||||
* bytes that can be written to the FLASH with a single transfer.
|
||||
*/
|
||||
#define SECTOR_SIZE 0x1000
|
||||
#define NUM_SECTORS 0x100
|
||||
|
||||
/*
|
||||
* Flash address to which data is to be written.
|
||||
*/
|
||||
#define TEST_ADDRESS 0x00
|
||||
#define UNIQUE_VALUE 0x05
|
||||
/*
|
||||
* 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 FLASH.
|
||||
*/
|
||||
#define MAX_DATA SECTOR_SIZE * NUM_SECTORS
|
||||
|
||||
/*
|
||||
* 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 FLASH_SPI_SELECT 0x01
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount);
|
||||
int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command);
|
||||
int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command);
|
||||
int WriteEnable(XIsf *InstancePtr);
|
||||
int SpiFlashPolledExample(XSpiPs *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 they are zeroed.
|
||||
*/
|
||||
static XSpiPs SpiInstance;
|
||||
static XIsf Isf;
|
||||
|
||||
/*
|
||||
* The following variables are used to read and write to the eeprom and they
|
||||
* are global to avoid having large buffers on the stack
|
||||
*/
|
||||
u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE];
|
||||
u8 WriteBuffer[MAX_DATA + DATA_OFFSET];
|
||||
u8 IsfWriteBuffer[XISF_CMD_SEND_EXTRA_BYTES + 1];
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to call the SPI Flash example.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
******************************************************************************/
|
||||
int main(void)
|
||||
{
|
||||
int Status;
|
||||
|
||||
xil_printf("SPI FLASH Polled Example Test \r\n");
|
||||
|
||||
/*
|
||||
* Run the Spi Interrupt example.
|
||||
*/
|
||||
Status = SpiFlashPolledExample(&SpiInstance,SPI_DEVICE_ID);
|
||||
if (Status != XST_SUCCESS) {
|
||||
xil_printf("SPI FLASH Polled Example Test Failed\r\n");
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
xil_printf("Successfully ran SPI FLASH Polled Example Test\r\n");
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* The purpose of this function is to illustrate how to use the XSpiPs
|
||||
* device driver in interrupt mode. This function writes and reads data
|
||||
* from a serial FLASH.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* This function calls other 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.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void FlashWriteSPI(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command);
|
||||
int SpiFlashPolledExample(XSpiPs *SpiInstancePtr,
|
||||
u16 SpiDeviceId)
|
||||
{
|
||||
u8 *BufferPtr;
|
||||
u8 UniqueValue;
|
||||
u32 Count;
|
||||
XSpiPs_Config *ConfigPtr; /* Pointer to Configuration ROM data */
|
||||
u32 TempAddress;
|
||||
|
||||
/*
|
||||
* Lookup the device configuration in the temporary CROM table. Use this
|
||||
* configuration info down below when initializing this component.
|
||||
*/
|
||||
ConfigPtr = XSpiPs_LookupConfig(SpiDeviceId);
|
||||
if (ConfigPtr == NULL) {
|
||||
return XST_DEVICE_NOT_FOUND;
|
||||
}
|
||||
|
||||
XSpiPs_CfgInitialize(SpiInstancePtr, ConfigPtr,
|
||||
ConfigPtr->BaseAddress);
|
||||
|
||||
/* Initialize the XILISF Library */
|
||||
XIsf_Initialize(&Isf, SpiInstancePtr, FLASH_SPI_SELECT,
|
||||
IsfWriteBuffer);
|
||||
|
||||
memset(WriteBuffer, 0x00, sizeof(WriteBuffer));
|
||||
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
|
||||
|
||||
/* Unprotect Sectors */
|
||||
FlashWrite(&Isf, 0, 0, XISF_WRITE_STATUS_REG);
|
||||
|
||||
FlashErase(&Isf, TEST_ADDRESS, MAX_DATA);
|
||||
|
||||
/*
|
||||
* Initialize the write buffer for a pattern to write to the FLASH
|
||||
* 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
|
||||
*/
|
||||
TempAddress = TEST_ADDRESS;
|
||||
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
|
||||
Count++, UniqueValue++, TempAddress++) {
|
||||
WriteBuffer[0] = (u8)(UniqueValue);
|
||||
FlashWrite(&Isf, TempAddress, 1, XISF_WRITE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the contents of the FLASH from TEST_ADDRESS, using Normal Read
|
||||
* command
|
||||
*/
|
||||
FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_READ);
|
||||
|
||||
/*
|
||||
* 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[DATA_OFFSET];
|
||||
|
||||
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
|
||||
Count++, UniqueValue++) {
|
||||
if (BufferPtr[Count] != (u8)(UniqueValue)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function waits till the 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 Serial Flash and
|
||||
waits till the WIP bit of the status register becomes 0.
|
||||
*
|
||||
******************************************************************************/
|
||||
int IsfWaitForFlashNotBusy(void)
|
||||
{
|
||||
int Status;
|
||||
u8 StatusReg;
|
||||
|
||||
while(1) {
|
||||
|
||||
/*
|
||||
* Get the Status Register.
|
||||
*/
|
||||
Status = XIsf_GetStatus(&Isf, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the flash is ready to accept the next command.
|
||||
* If so break.
|
||||
*/
|
||||
StatusReg = ReadBuffer[BYTE2];
|
||||
if((StatusReg & XISF_SR_IS_READY_MASK) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*
|
||||
* This function writes to the serial FLASH connected to the SPI interface.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf component to use.
|
||||
* @param Address contains the address to write data to in the FLASH.
|
||||
* @param ByteCount contains the number of bytes to write.
|
||||
* @param Command is the command used to write data to the flash.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command)
|
||||
{
|
||||
XIsf_WriteParam WriteParam;
|
||||
|
||||
int Status;
|
||||
|
||||
WriteEnable(InstancePtr);
|
||||
|
||||
WriteParam.Address = Address;
|
||||
WriteParam.NumBytes = ByteCount;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
|
||||
/*
|
||||
* Perform the Write operation.
|
||||
*/
|
||||
Status = XIsf_Write(&Isf, Command, (void*) &WriteParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This function reads from the serial FLASH connected to the
|
||||
* SPI interface.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf component to use.
|
||||
* @param Address contains the address to read data from in the FLASH.
|
||||
* @param ByteCount contains the number of bytes to read.
|
||||
* @param Command is the command used to read data from the flash.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command)
|
||||
{
|
||||
XIsf_ReadParam ReadParam;
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ByteCount;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
|
||||
/*
|
||||
* Perform the Read operation.
|
||||
*/
|
||||
Status = XIsf_Read(&Isf, Command, (void*) &ReadParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*
|
||||
* This function erases the sectors in the serial FLASH connected to the
|
||||
* SPI interface.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf component to use.
|
||||
* @param Address contains the address of the first sector which needs to
|
||||
* be erased.
|
||||
* @param ByteCount contains the total size to be erased.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount)
|
||||
{
|
||||
int Status;
|
||||
int Sector;
|
||||
|
||||
/*
|
||||
* If the erase size is less than the total size of the flash, use
|
||||
* sector erase command
|
||||
*/
|
||||
for (Sector = 0; Sector < ((ByteCount / SECTOR_SIZE) + 1); Sector++) {
|
||||
|
||||
/*
|
||||
* Write enable instruction has to be executed prior to
|
||||
* any Write operation.
|
||||
*/
|
||||
WriteEnable(InstancePtr);
|
||||
|
||||
/*
|
||||
* Perform the Sector Erase operation.
|
||||
*/
|
||||
Status = XIsf_Erase(InstancePtr, XISF_SECTOR_ERASE, Address);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Address += SECTOR_SIZE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function performs the write enable operation.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf component to use.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
int WriteEnable(XIsf *InstancePtr)
|
||||
{
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
return XST_SUCCESS;
|
||||
}
|
972
lib/sw_services/xilisf/examples/xilisf_stm_quad_flash_example.c
Normal file
972
lib/sw_services/xilisf/examples/xilisf_stm_quad_flash_example.c
Normal file
|
@ -0,0 +1,972 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
* XILINX 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 xilisf_stm_quad_flash_example.c
|
||||
*
|
||||
* This file contains a design example using the In-system and Serial Flash
|
||||
* Library (XilIsf) for Reading/Writing to a STM (Numonyx) N25QXX Quad Serial
|
||||
* Flash Device. This example shows the Erase, Dual/Quad Read and Dual/Quad
|
||||
* Write features.
|
||||
*
|
||||
* This example
|
||||
* - Erases a Sector
|
||||
* - Writes to a Page within the Erased Sector
|
||||
* - Reads back the Page that is written and compares the data
|
||||
*
|
||||
* This example has been tested with a Numonyx Serial Flash Memory (N25Q128) on
|
||||
* a Xilinx KC705 board. For further details about the Flash device refer the
|
||||
* Numonyx Serial Flash Memory (N25Q128) data sheet.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -----------------------------------------------
|
||||
* 2.04a sdm 08/25/11 First release
|
||||
* 3.02a adk 07/08/13 Fixed the CR 721229, by setting the proper QSPI options.
|
||||
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
|
||||
* instead of driver handler.
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h" /* EDK generated parameters */
|
||||
#include "xintc.h" /* Interrupt controller device driver */
|
||||
#include <xilisf.h> /* Serial Flash Library header file */
|
||||
#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 ISF_SPI_SELECT 0x01
|
||||
|
||||
/*
|
||||
* Number of bytes per page in the flash device.
|
||||
*/
|
||||
#define ISF_PAGE_SIZE 256
|
||||
|
||||
/*
|
||||
* Address of the page to perform Erase, Write and Read operations.
|
||||
*/
|
||||
#define ISF_TEST_ADDRESS 0x010000;
|
||||
#define ISF_TEST_BYTE 0x03 /* Test Byte value written */
|
||||
|
||||
/*
|
||||
* The following definitions specify the number of dummy bytes associated with
|
||||
* various Read commands and the number of dummy bytes to ignore in the data
|
||||
* read from the flash, through those Read commands. This is apart from the
|
||||
* dummy bytes returned in response to the command and address transmitted.
|
||||
*/
|
||||
/*
|
||||
* After transmitting Dual Read command and address on DIO0, the quad spi
|
||||
* device configures DIO0 and DIO1 in input mode and receives data on both
|
||||
* DIO0 and DIO1 for 8 dummy clock cycles. So we end up with 16 dummy bits
|
||||
* in DRR. The same logic applies for Dual IO Read (8 dummy clock cycles =
|
||||
* 16 dummy bits), Quad Read command (8 dummy clock cycles = 32 dummy bits)
|
||||
* and Quad IO Read command (10 dummy clock cycles = 40 dummy bits)
|
||||
*/
|
||||
/*
|
||||
* The number of dummy cycles is configurable in the flash device. Please refer
|
||||
* to the flash datasheet for more details.
|
||||
*/
|
||||
#define DUAL_READ_DUMMY_BYTES 2
|
||||
#define DUAL_IO_READ_DUMMY_BYTES 2
|
||||
#define QUAD_READ_DUMMY_BYTES 4
|
||||
#define QUAD_IO_READ_DUMMY_BYTES 5
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
static int IsfWaitForFlashNotBusy(void);
|
||||
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 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 XIsf Isf;
|
||||
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; /* State of Spi Transfer */
|
||||
static int ErrorCount; /* Errors occurred during Spi transfers */
|
||||
|
||||
/*
|
||||
* The user needs to allocate a buffer to be used by the In-system and Serial
|
||||
* Flash Library to perform any read/write operations on the Serial Flash
|
||||
* device.
|
||||
* User applications must pass the address of this memory to the Library in
|
||||
* Serial Flash Initialization function, for the Library to work.
|
||||
* For Write operations:
|
||||
* - The size of this buffer should be equal to the Number of bytes to be
|
||||
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
|
||||
* - The size of this buffer should be large enough for usage across all the
|
||||
* applications that use a common instance of the Serial Flash.
|
||||
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
|
||||
* to the Serial Flash, through a single Write operation.
|
||||
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
|
||||
* application only reads from the Serial Flash (no write operations).
|
||||
*/
|
||||
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
|
||||
|
||||
/*
|
||||
* Buffers used during Read/Write transactions.
|
||||
*/
|
||||
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + 5]; /* Read Buffer */
|
||||
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
|
||||
|
||||
/************************** Function Definitions ******************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to execute the Numonyx Quad Serial Flash Read/Write example.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
******************************************************************************/
|
||||
int main()
|
||||
{
|
||||
int Status;
|
||||
u32 Index;
|
||||
u32 Address;
|
||||
XIsf_WriteParam WriteParam;
|
||||
XIsf_ReadParam ReadParam;
|
||||
|
||||
/*
|
||||
* Initialize the SPI driver so that it's ready to use,
|
||||
* specify the device ID that is generated in xparameters.h.
|
||||
*/
|
||||
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
|
||||
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.
|
||||
*/
|
||||
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
|
||||
|
||||
/*
|
||||
* Start the SPI driver so that interrupts and the device are enabled.
|
||||
*/
|
||||
XSpi_Start(&Spi);
|
||||
|
||||
/*
|
||||
* Set the QSPI options
|
||||
*/
|
||||
Status = XIsf_SetSpiConfiguration(&Isf, &Spi,
|
||||
XSP_MASTER_OPTION | XSP_MANUAL_SSELECT_OPTION,
|
||||
XISF_SPI_PRESCALER);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the Serial Flash Library.
|
||||
*/
|
||||
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set The transfer Mode to Interrupt
|
||||
*/
|
||||
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
|
||||
|
||||
/*
|
||||
* Specify the address in the Serial Flash for the Erase/Write/Read
|
||||
* operations.
|
||||
*/
|
||||
Address = ISF_TEST_ADDRESS;
|
||||
|
||||
/*
|
||||
* The following code Erases a Sector in the Numonyx Serial Flash.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Sector Erase operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address within the Serial Flash where the data is to be written.
|
||||
* - Number of bytes to be written to the Serial Flash.
|
||||
* - Write Buffer which contains the data to be written to the Serial
|
||||
* Flash.
|
||||
*/
|
||||
WriteParam.Address = Address;
|
||||
WriteParam.NumBytes = ISF_PAGE_SIZE;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
|
||||
/*
|
||||
* Prepare the write buffer. Fill in the data need to be written into
|
||||
* Serial Flash.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Write(&Isf, XISF_DUAL_IP_PAGE_WRITE, (void*) &WriteParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read from the flash using Dual Output Fast Read command.
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
* - Number of dummy bytes for the read command.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ISF_PAGE_SIZE;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
ReadParam.NumDummyBytes = DUAL_READ_DUMMY_BYTES;
|
||||
|
||||
/*
|
||||
* Clear the read Buffer.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES +
|
||||
DUAL_READ_DUMMY_BYTES; Index++) {
|
||||
ReadBuffer[Index] = 0x0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the read operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Read(&Isf, XISF_DUAL_OP_FAST_READ, (void*) &ReadParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the data read against the data Written.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES +
|
||||
DUAL_READ_DUMMY_BYTES] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Move to the next page in the flash.
|
||||
*/
|
||||
Address += ISF_PAGE_SIZE;
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address within the Serial Flash where the data is to be written.
|
||||
* - Number of bytes to be written to the Serial Flash.
|
||||
* - Write Buffer which contains the data to be written to the Serial
|
||||
* Flash.
|
||||
*/
|
||||
WriteParam.Address = Address;
|
||||
WriteParam.NumBytes = ISF_PAGE_SIZE;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
|
||||
/*
|
||||
* Prepare the write buffer. Fill in the data need to be written into
|
||||
* Serial Flash.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Write(&Isf, XISF_DUAL_IP_EXT_PAGE_WRITE, (void*) &WriteParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read from the flash using Dual Input/Output Fast Read command.
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
* - Number of dummy bytes for the read command.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ISF_PAGE_SIZE;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
ReadParam.NumDummyBytes = DUAL_IO_READ_DUMMY_BYTES;
|
||||
|
||||
/*
|
||||
* Clear the read Buffer.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES +
|
||||
DUAL_IO_READ_DUMMY_BYTES; Index++) {
|
||||
ReadBuffer[Index] = 0x0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the read operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Read(&Isf, XISF_DUAL_IO_FAST_READ, (void*) &ReadParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the data read against the data Written.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES +
|
||||
DUAL_IO_READ_DUMMY_BYTES] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Move to the next page in the flash.
|
||||
*/
|
||||
Address += ISF_PAGE_SIZE;
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address within the Serial Flash where the data is to be written.
|
||||
* - Number of bytes to be written to the Serial Flash.
|
||||
* - Write Buffer which contains the data to be written to the Serial
|
||||
* Flash.
|
||||
*/
|
||||
WriteParam.Address = Address;
|
||||
WriteParam.NumBytes = ISF_PAGE_SIZE;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
|
||||
/*
|
||||
* Prepare the write buffer. Fill in the data need to be written into
|
||||
* Serial Flash.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Write(&Isf, XISF_QUAD_IP_PAGE_WRITE, (void*) &WriteParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read from the flash using Quad Output Fast Read command.
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
* - Number of dummy bytes for the read command.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ISF_PAGE_SIZE;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
ReadParam.NumDummyBytes = QUAD_READ_DUMMY_BYTES;
|
||||
|
||||
/*
|
||||
* Clear the read Buffer.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES +
|
||||
QUAD_READ_DUMMY_BYTES; Index++) {
|
||||
ReadBuffer[Index] = 0x0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the read operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Read(&Isf, XISF_QUAD_OP_FAST_READ, (void*) &ReadParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the data read against the data Written.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES +
|
||||
QUAD_READ_DUMMY_BYTES] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Move to the next page in the flash.
|
||||
*/
|
||||
Address += ISF_PAGE_SIZE;
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address within the Serial Flash where the data is to be written.
|
||||
* - Number of bytes to be written to the Serial Flash.
|
||||
* - Write Buffer which contains the data to be written to the Serial
|
||||
* Flash.
|
||||
*/
|
||||
WriteParam.Address = Address;
|
||||
WriteParam.NumBytes = ISF_PAGE_SIZE;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
|
||||
/*
|
||||
* Prepare the write buffer. Fill in the data need to be written into
|
||||
* Serial Flash.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Write(&Isf, XISF_QUAD_IP_EXT_PAGE_WRITE,
|
||||
(void*) &WriteParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read from the flash using Quad Input/Output Fast Read command.
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
* - Number of dummy bytes for the read command.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ISF_PAGE_SIZE;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
ReadParam.NumDummyBytes = QUAD_IO_READ_DUMMY_BYTES;
|
||||
|
||||
/*
|
||||
* Clear the read Buffer.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES +
|
||||
QUAD_IO_READ_DUMMY_BYTES; Index++) {
|
||||
ReadBuffer[Index] = 0x0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the read operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Read(&Isf, XISF_QUAD_IO_FAST_READ, (void*) &ReadParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the data read against the data written.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES +
|
||||
QUAD_IO_READ_DUMMY_BYTES] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function waits till the Numonyx 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 Serial Flash and
|
||||
* waits till the Serial Flash is ready to accept next command.
|
||||
*
|
||||
******************************************************************************/
|
||||
int IsfWaitForFlashNotBusy(void)
|
||||
{
|
||||
int Status;
|
||||
u8 StatusReg;
|
||||
|
||||
while(1) {
|
||||
|
||||
/*
|
||||
* Get the Status Register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_GetStatus(&Isf, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the Serial Flash is ready to accept the next
|
||||
* command. If so break.
|
||||
*/
|
||||
StatusReg = ReadBuffer[BYTE2];
|
||||
if((StatusReg & XISF_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, u16 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, specify real mode so that
|
||||
* the SPI can cause interrupts through 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;
|
||||
}
|
383
lib/sw_services/xilisf/examples/xilisf_stm_rdwr_polled_example.c
Normal file
383
lib/sw_services/xilisf/examples/xilisf_stm_rdwr_polled_example.c
Normal file
|
@ -0,0 +1,383 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 - 2015 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
|
||||
* XILINX 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 xilisf_stm_rdwr_polled_example.c
|
||||
*
|
||||
* This file contains a design example using the In-system and Serial Flash
|
||||
* Library (XilIsf) for Reading/Writing to a STM (Numonyx) M25P16 Serial Flash
|
||||
* Device with the Spi driver in polled mode of operation. This example shows
|
||||
* the Erase, Read and Write features.
|
||||
*
|
||||
* This example
|
||||
* - Erases a Sector
|
||||
* - Writes to a Page within the Erased Sector
|
||||
* - Reads back the Page that is written and compares the data.
|
||||
*
|
||||
* This example has been tested with a STM (Numonyx) M25P16 device on a Xilinx
|
||||
* Spartan-3A Starter Kit board and AC701 board with a Micron flash N25Q256A
|
||||
* (32MB, supporting 4 Byte addressing mode).
|
||||
*
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- --- -------- -----------------------------------------------
|
||||
* 1.00a sdm 04/02/08 First release
|
||||
* 2.00a ktn 11/22/09 The Spi Driver APIs have changed. Replaced the call
|
||||
* to XSpi_mIntrGlobalDisable with XSpi_IntrGlobalDisable.
|
||||
* 5.2 asa 05/12/15 Added support for Micron N25Q256A flash part which
|
||||
* supports 4 byte addressing.
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h" /* EDK generated parameters */
|
||||
#include "xilisf.h" /* Serial Flash Library header file */
|
||||
|
||||
/************************** 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
|
||||
|
||||
/*
|
||||
* 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 ISF_SPI_SELECT 0x01
|
||||
|
||||
/*
|
||||
* Number of bytes per page in the flash device.
|
||||
*/
|
||||
#define ISF_PAGE_SIZE 256
|
||||
|
||||
/*
|
||||
* Address of the page to perform Erase, Write and Read operations.
|
||||
*/
|
||||
#define ISF_TEST_ADDRESS 0x010000;
|
||||
#define ISF_TEST_BYTE 0x36 /* Test Byte offset value written */
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
static int IsfWaitForFlashNotBusy(void);
|
||||
|
||||
/************************** 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 XIsf Isf;
|
||||
static XSpi Spi;
|
||||
|
||||
/*
|
||||
* The user needs to allocate a buffer to be used by the In-system and Serial
|
||||
* Flash Library to perform any read/write operations on the Serial Flash
|
||||
* device.
|
||||
* User applications must pass the address of this memory to the Library in
|
||||
* Serial Flash Initialization function, for the Library to work.
|
||||
* For Write operations:
|
||||
* - The size of this buffer should be equal to the Number of bytes to be
|
||||
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
|
||||
* - The size of this buffer should be large enough for usage across all the
|
||||
* applications that use a common instance of the Serial Flash.
|
||||
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
|
||||
* to the Serial Flash, through a single Write operation.
|
||||
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
|
||||
* application only reads from the Serial Flash (no write operations).
|
||||
* For 4 byte addressing mode support, to account for the extra address bye
|
||||
* the buffer size is incremented by 1.
|
||||
*/
|
||||
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + 1];
|
||||
|
||||
/*
|
||||
* Buffers used during Read/Write transactions.
|
||||
*/
|
||||
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + 1]; /* Read Buffer */
|
||||
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
|
||||
|
||||
/************************** Function Definitions ******************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to execute the STM Serial Flash Read/Write polled example.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
******************************************************************************/
|
||||
int main()
|
||||
{
|
||||
int Status;
|
||||
u32 Index;
|
||||
u32 Address;
|
||||
XIsf_WriteParam WriteParam;
|
||||
XIsf_ReadParam ReadParam;
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the SPI driver so that it's ready to use,
|
||||
* specify the device ID that is generated in xparameters.h.
|
||||
*/
|
||||
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the SPI driver so that the device is enabled.
|
||||
*/
|
||||
XSpi_Start(&Spi);
|
||||
|
||||
/*
|
||||
* Disable Global interrupt to use the Spi driver in polled mode
|
||||
* operation.
|
||||
*/
|
||||
XSpi_IntrGlobalDisable(&Spi);
|
||||
|
||||
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Specify the address in the Serial Flash for the Erase/Write/Read
|
||||
* operations.
|
||||
*/
|
||||
Address = ISF_TEST_ADDRESS;
|
||||
|
||||
/*
|
||||
* Check is the flash part is micron in which case, switch to 4 byte
|
||||
* addressing mode.
|
||||
*/
|
||||
if (Isf.ManufacturerID == XISF_MANUFACTURER_ID_MICRON) {
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
XIsf_MicronFlashEnter4BAddMode(&Isf);
|
||||
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address within the Serial Flash where the data is to be written.
|
||||
* - Number of bytes to be written to the Serial Flash.
|
||||
* - Write Buffer which contains the data to be written to the Serial
|
||||
* Flash.
|
||||
*/
|
||||
WriteParam.Address = Address;
|
||||
WriteParam.NumBytes = ISF_PAGE_SIZE;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
|
||||
/*
|
||||
* Prepare the write buffer. Fill in the data need to be written into
|
||||
* Serial Flash.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
|
||||
}
|
||||
|
||||
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ISF_PAGE_SIZE;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
|
||||
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the data read against the data Written. For Micron flash
|
||||
* which supports 4 Byte mode, comparison should take care of the extra
|
||||
* address byte.
|
||||
*/
|
||||
if (Isf.ManufacturerID == XISF_MANUFACTURER_ID_MICRON) {
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* For micron flash part supporting 4 byte ddressing mode, exit from
|
||||
* 4 Byte mode.
|
||||
*/
|
||||
if (Isf.ManufacturerID == XISF_MANUFACTURER_ID_MICRON) {
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
XIsf_MicronFlashExit4BAddMode(&Isf);
|
||||
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
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 Serial Flash and
|
||||
* waits till the Serial Flash is ready to accept next command.
|
||||
*
|
||||
******************************************************************************/
|
||||
int IsfWaitForFlashNotBusy(void)
|
||||
{
|
||||
int Status;
|
||||
u8 StatusReg;
|
||||
|
||||
while(1) {
|
||||
|
||||
/*
|
||||
* Get the Status Register.
|
||||
*/
|
||||
Status = XIsf_GetStatus(&Isf, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the Serial Flash is ready to accept the next
|
||||
* command. If so break.
|
||||
*/
|
||||
StatusReg = ReadBuffer[BYTE2];
|
||||
if((StatusReg & XISF_SR_IS_READY_MASK) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
585
lib/sw_services/xilisf/examples/xilisf_stm_read_write_example.c
Normal file
585
lib/sw_services/xilisf/examples/xilisf_stm_read_write_example.c
Normal file
|
@ -0,0 +1,585 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 - 2015 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
|
||||
* XILINX 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 xilisf_stm_read_write_example.c
|
||||
*
|
||||
* This file contains a design example using the In-system and Serial Flash
|
||||
* Library (XilIsf) for Reading/Writing to a STM (Numonyx) M25P16 Serial Flash
|
||||
* Device. This example shows the Erase, Read and Write features.
|
||||
*
|
||||
* This example
|
||||
* - Erases a Sector
|
||||
* - Writes to a Page within the Erased Sector
|
||||
* - Reads back the Page that is written and compares the data
|
||||
*
|
||||
* This example has been tested with a STM (Numonyx) M25P16 device on Xilinx
|
||||
* Spartan-3A Starter Kit board.
|
||||
*
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -----------------------------------------------
|
||||
* 1.00a sdm 03/17/08 First release
|
||||
* 2.00a ktn 11/22/09 Updated to use HAL processor APIs.
|
||||
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
|
||||
* instead of driver handler.
|
||||
* 5.2 asa 05/12/15 Added support for Micron N25Q256A flash.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h" /* EDK generated parameters */
|
||||
#include "xintc.h" /* Interrupt controller device driver */
|
||||
#include <xilisf.h> /* Serial Flash Library header file */
|
||||
#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 ISF_SPI_SELECT 0x01
|
||||
|
||||
/*
|
||||
* Number of bytes per page in the flash device.
|
||||
*/
|
||||
#define ISF_PAGE_SIZE 256
|
||||
|
||||
/*
|
||||
* Address of the page to perform Erase, Write and Read operations.
|
||||
*/
|
||||
#define ISF_TEST_ADDRESS 0x010000;
|
||||
#define ISF_TEST_BYTE 0x05 /* Test Byte offset value written */
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
static int IsfWaitForFlashNotBusy(void);
|
||||
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 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 XIsf Isf;
|
||||
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; /* State of Spi Transfer */
|
||||
static int ErrorCount; /* Errors occurred during Spi transfers */
|
||||
|
||||
/*
|
||||
* The user needs to allocate a buffer to be used by the In-system and Serial
|
||||
* Flash Library to perform any read/write operations on the Serial Flash
|
||||
* device.
|
||||
* User applications must pass the address of this memory to the Library in
|
||||
* Serial Flash Initialization function, for the Library to work.
|
||||
* For Write operations:
|
||||
* - The size of this buffer should be equal to the Number of bytes to be
|
||||
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
|
||||
* - The size of this buffer should be large enough for usage across all the
|
||||
* applications that use a common instance of the Serial Flash.
|
||||
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
|
||||
* to the Serial Flash, through a single Write operation.
|
||||
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
|
||||
* application only reads from the Serial Flash (no write operations).
|
||||
*/
|
||||
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + 1];
|
||||
|
||||
/*
|
||||
* Buffers used during Read/Write transactions.
|
||||
*/
|
||||
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + 1]; /* Read Buffer */
|
||||
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
|
||||
|
||||
/************************** Function Definitions ******************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to execute the STM Serial Flash Read/Write example.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
******************************************************************************/
|
||||
int main()
|
||||
{
|
||||
int Status;
|
||||
u32 Index;
|
||||
u32 Address;
|
||||
XIsf_WriteParam WriteParam;
|
||||
XIsf_ReadParam ReadParam;
|
||||
|
||||
/*
|
||||
* Initialize the SPI driver so that it's ready to use,
|
||||
* specify the device ID that is generated in xparameters.h.
|
||||
*/
|
||||
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
|
||||
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.
|
||||
*/
|
||||
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
|
||||
|
||||
/*
|
||||
* Start the SPI driver so that interrupts and the device are enabled.
|
||||
*/
|
||||
XSpi_Start(&Spi);
|
||||
|
||||
/*
|
||||
* Initialize the Serial Flash Library.
|
||||
*/
|
||||
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set The transfer Mode to Interrupt
|
||||
*/
|
||||
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
|
||||
|
||||
/*
|
||||
* Specify the address in the Serial Flash for the Erase/Write/Read
|
||||
* operations.
|
||||
*/
|
||||
Address = ISF_TEST_ADDRESS;
|
||||
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check is the flash part is micron in which case, switch to 4 byte
|
||||
* addressing mode.
|
||||
*/
|
||||
if (Isf.ManufacturerID == XISF_MANUFACTURER_ID_MICRON) {
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
TransferInProgress = TRUE;
|
||||
XIsf_MicronFlashEnter4BAddMode(&Isf);
|
||||
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address within the Serial Flash where the data is to be written.
|
||||
* - Number of bytes to be written to the Serial Flash.
|
||||
* - Write Buffer which contains the data to be written to the Serial
|
||||
* Flash.
|
||||
*/
|
||||
WriteParam.Address = Address;
|
||||
WriteParam.NumBytes = ISF_PAGE_SIZE;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
|
||||
/*
|
||||
* Prepare the write buffer. Fill in the data need to be written into
|
||||
* Serial Flash.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
|
||||
}
|
||||
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ISF_PAGE_SIZE;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the data read against the data Written.
|
||||
*/
|
||||
if (Isf.ManufacturerID == XISF_MANUFACTURER_ID_MICRON) {
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Isf.ManufacturerID == XISF_MANUFACTURER_ID_MICRON) {
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
TransferInProgress = TRUE;
|
||||
XIsf_MicronFlashExit4BAddMode(&Isf);
|
||||
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
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 Serial Flash and
|
||||
* waits till the Serial Flash is ready to accept next command.
|
||||
*
|
||||
******************************************************************************/
|
||||
int IsfWaitForFlashNotBusy(void)
|
||||
{
|
||||
int Status;
|
||||
u8 StatusReg;
|
||||
|
||||
while(1) {
|
||||
|
||||
/*
|
||||
* Get the Status Register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_GetStatus(&Isf, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the Serial Flash is ready to accept the next
|
||||
* command. If so break.
|
||||
*/
|
||||
StatusReg = ReadBuffer[BYTE2];
|
||||
if((StatusReg & XISF_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, u16 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, specify real mode so that
|
||||
* the SPI can cause interrupts through 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;
|
||||
}
|
754
lib/sw_services/xilisf/examples/xilisf_stm_spr_example.c
Normal file
754
lib/sw_services/xilisf/examples/xilisf_stm_spr_example.c
Normal file
|
@ -0,0 +1,754 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
* XILINX 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 xilisf_stm_spr_example.c
|
||||
*
|
||||
* This file contains a design example using the Xilinx In-system and Serial
|
||||
* Flash Library (XilIsf). This example shows the usage of Sector Erase, Sector
|
||||
* Protection, Read and Write features.
|
||||
|
||||
* This example
|
||||
* - Erases a Sector
|
||||
* - Writes to a Page within the erased Sector
|
||||
* - Enables the Sector Protection so that all the sectors are Write protected
|
||||
* - Erases a Page (This should not happen as the Sectors are Write protected
|
||||
* - Reads back the Page that is written and compares the data.
|
||||
*
|
||||
* This example has been tested with a STM (Numonyx) Serial Flash Memory
|
||||
* (M25P16) on a Xilinx Spartan-3A Starter Kit board. For further details about
|
||||
* the Flash device refer to the STM (Numonyx) Serial Flash Memory (M25P16)
|
||||
* data sheet.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -----------------------------------------------
|
||||
* 1.00a sdm 03/17/08 First release
|
||||
* 2.00a ktn 11/22/09 Updated to use HAL processor APIs.
|
||||
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
|
||||
* instead of driver handler.
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h" /* EDK generated parameters */
|
||||
#include "xintc.h" /* Interrupt controller device driver */
|
||||
#include "xspi.h" /* SPI device driver */
|
||||
#include <xilisf.h> /* Serial Flash Library header file */
|
||||
#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 Serial Flash on the SPI bus, this signal is typically
|
||||
* connected to the chip select of the device.
|
||||
*/
|
||||
#define ISF_SPI_SELECT 0x01
|
||||
|
||||
/*
|
||||
* Number of bytes per page in the Serial Flash.
|
||||
*/
|
||||
#define ISF_PAGE_SIZE 256
|
||||
|
||||
/*
|
||||
* Address of the page to perform Erase, Write and Read operations.
|
||||
*/
|
||||
#define ISF_TEST_ADDRESS 0x010000;
|
||||
#define ISF_TEST_BYTE 0x15 /* Test Byte offset value written */
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
static int IsfWaitForFlashNotBusy(void);
|
||||
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 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 XIsf Isf;
|
||||
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.
|
||||
*/
|
||||
static int ErrorCount;
|
||||
|
||||
/*
|
||||
* The user needs to allocate a buffer to be used by the In-system and Serial
|
||||
* Flash Library to perform any read/write operations on the Serial Flash
|
||||
* device.
|
||||
* User applications must pass the address of this memory to the Library in
|
||||
* Serial Flash Initialization function, for the Library to work.
|
||||
* For Write operations:
|
||||
* - The size of this buffer should be equal to the Number of bytes to be
|
||||
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
|
||||
* - The size of this buffer should be large enough for usage across all the
|
||||
* applications that use a common instance of the Serial Flash.
|
||||
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
|
||||
* to the Serial Flash, through a single Write operation.
|
||||
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
|
||||
* application only reads from the Serial Flash (no write operations).
|
||||
*/
|
||||
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
|
||||
|
||||
/*
|
||||
* Buffers used during read and write transactions.
|
||||
*/
|
||||
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
|
||||
u8 WriteBuffer[ISF_PAGE_SIZE];
|
||||
|
||||
/************************** Function Definitions ******************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to execute the STM Serial Flash SPR example.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
******************************************************************************/
|
||||
int main()
|
||||
{
|
||||
int Status;
|
||||
u32 Index;
|
||||
u32 Address;
|
||||
XIsf_WriteParam WriteParam;
|
||||
XIsf_ReadParam ReadParam;
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the SPI driver so that it's ready to use,
|
||||
* specify the device ID that is generated in xparameters.h.
|
||||
*/
|
||||
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
|
||||
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.
|
||||
*/
|
||||
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
|
||||
|
||||
/*
|
||||
* Start the SPI driver so that interrupts and the device are enabled.
|
||||
*/
|
||||
XSpi_Start(&Spi);
|
||||
|
||||
/*
|
||||
* Initialize the Serial Flash Library.
|
||||
*/
|
||||
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set The transfer Mode to Interrupt
|
||||
*/
|
||||
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
|
||||
|
||||
/*
|
||||
* Specify the address in the Serial Flash for the Erase/Write/Read
|
||||
* operations.
|
||||
*/
|
||||
Address = ISF_TEST_ADDRESS;
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Sector Erase operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address within the Serial Flash where the data is to be written.
|
||||
* - Number of bytes to be written to the Serial Flash.
|
||||
* - Write Buffer which contains the data to be written to the Serial
|
||||
* Flash.
|
||||
*/
|
||||
WriteParam.Address = Address;
|
||||
WriteParam.NumBytes = ISF_PAGE_SIZE;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
|
||||
/*
|
||||
* Prepare the write buffer. Fill in the data that needs to be written
|
||||
* to the Serial Flash.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the sector protection register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set all the block protection bits in the sector protection register
|
||||
* value read above and write it back to the sector protection register
|
||||
* to disable protection for all sectors.
|
||||
*/
|
||||
WriteBuffer[BYTE1] = ReadBuffer[BYTE2] |
|
||||
(XISF_SR_BLOCK_PROTECT_MASK);
|
||||
|
||||
/*
|
||||
* Enable the sector protection.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Sector Erase operation. This should not work as sector
|
||||
* protection is enabled for all the sectors.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the sector protection register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear all the block protection bits in the sector protection register
|
||||
* value read above and write it back to the sector protection register
|
||||
* to disable protection for all sectors.
|
||||
*/
|
||||
WriteBuffer[BYTE1] = ReadBuffer[BYTE2] &
|
||||
~(XISF_SR_BLOCK_PROTECT_MASK);
|
||||
|
||||
/*
|
||||
* Disable the sector protection.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ISF_PAGE_SIZE;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
|
||||
/*
|
||||
* Perform the Read operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the data read against the data written.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
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 Serial Flash and
|
||||
waits till the WIP bit of the status register becomes 0.
|
||||
*
|
||||
******************************************************************************/
|
||||
int IsfWaitForFlashNotBusy(void)
|
||||
{
|
||||
int Status;
|
||||
u8 StatusReg;
|
||||
|
||||
while(1) {
|
||||
|
||||
/*
|
||||
* Get the Status Register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_GetStatus(&Isf, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is in progress.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
|
||||
/*
|
||||
* Check if there are any errors in the transaction.
|
||||
*/
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the flash is ready to accept the next command.
|
||||
* If so break.
|
||||
*/
|
||||
StatusReg = ReadBuffer[BYTE2];
|
||||
if((StatusReg & XISF_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, u16 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;
|
||||
}
|
|
@ -0,0 +1,849 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
* XILINX 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 xilisf_winbond_quad_flash_example.c
|
||||
*
|
||||
* This file contains a design example using the In-system and Serial Flash
|
||||
* Library (XilIsf) for Reading/Writing to a Winbond W25QXX Quad Serial Flash
|
||||
* Device. This example shows the Erase, Dual/Quad Read and Quad Write
|
||||
* features.
|
||||
*
|
||||
* This example
|
||||
* - Erases a Sector
|
||||
* - Writes to a Page within the Erased Sector
|
||||
* - Reads back the Page that is written and compares the data
|
||||
*
|
||||
* This example has been tested with a Winbond Serial Flash Memory (W25Q64) on
|
||||
* a Xilinx SP605 board. For further details about the Flash device refer the
|
||||
* Winbond Serial Flash Memory (W25Q64) data sheet.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -----------------------------------------------
|
||||
* 2.04a sdm 08/25/11 First release
|
||||
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
|
||||
* instead of driver handler.
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h" /* EDK generated parameters */
|
||||
#include "xintc.h" /* Interrupt controller device driver */
|
||||
#include <xilisf.h> /* Serial Flash Library header file */
|
||||
#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 ISF_SPI_SELECT 0x01
|
||||
|
||||
/*
|
||||
* Number of bytes per page in the flash device.
|
||||
*/
|
||||
#define ISF_PAGE_SIZE 256
|
||||
|
||||
/*
|
||||
* Address of the page to perform Erase, Write and Read operations.
|
||||
*/
|
||||
#define ISF_TEST_ADDRESS 0x010000;
|
||||
#define ISF_TEST_BYTE 0x03 /* Test Byte value written */
|
||||
|
||||
/*
|
||||
* The following definitions specify the number of dummy bytes to ignore in the
|
||||
* data read from the flash, through various Read commands. This is apart from
|
||||
* the dummy bytes returned in reponse to the command and address transmitted.
|
||||
*/
|
||||
/*
|
||||
* After transmitting Dual Read command and address on DIO0, the quad spi device
|
||||
* configures DIO0 and DIO1 in input mode and receives data on both DIO0 and
|
||||
* DIO1 for 8 dummy clock cycles. So we end up with 16 dummy bits in DRR. The
|
||||
* same logic applies Quad read command, so we end up with 4 dummy bytes in that
|
||||
* case.
|
||||
*/
|
||||
/*
|
||||
* Please refer to the flash datasheet for more details about the number of dummy
|
||||
* cycles associated with each command.
|
||||
*/
|
||||
#define DUAL_READ_DUMMY_BYTES 2
|
||||
#define QUAD_READ_DUMMY_BYTES 4
|
||||
|
||||
#define DUAL_IO_READ_DUMMY_BYTES 1
|
||||
#define QUAD_IO_READ_DUMMY_BYTES 3
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
static int IsfWaitForFlashNotBusy(void);
|
||||
static int SpiFlashQuadEnable(void);
|
||||
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 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 XIsf Isf;
|
||||
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; /* State of Spi Transfer */
|
||||
static int ErrorCount; /* Errors occurred during Spi transfers */
|
||||
|
||||
/*
|
||||
* The user needs to allocate a buffer to be used by the In-system and Serial
|
||||
* Flash Library to perform any read/write operations on the Serial Flash
|
||||
* device.
|
||||
* User applications must pass the address of this memory to the Library in
|
||||
* Serial Flash Initialization function, for the Library to work.
|
||||
* For Write operations:
|
||||
* - The size of this buffer should be equal to the Number of bytes to be
|
||||
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
|
||||
* - The size of this buffer should be large enough for usage across all the
|
||||
* applications that use a common instance of the Serial Flash.
|
||||
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
|
||||
* to the Serial Flash, through a single Write operation.
|
||||
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
|
||||
* application only reads from the Serial Flash (no write operations).
|
||||
*/
|
||||
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
|
||||
|
||||
/*
|
||||
* Buffers used during Read/Write transactions.
|
||||
*/
|
||||
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + 4]; /* Read Buffer */
|
||||
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
|
||||
|
||||
/************************** Function Definitions ******************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to execute the Winbond Quad Serial Flash Read/Write example.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
******************************************************************************/
|
||||
int main()
|
||||
{
|
||||
int Status;
|
||||
u32 Index;
|
||||
u32 Address;
|
||||
XIsf_WriteParam WriteParam;
|
||||
XIsf_ReadParam ReadParam;
|
||||
|
||||
/*
|
||||
* Initialize the SPI driver so that it's ready to use,
|
||||
* specify the device ID that is generated in xparameters.h.
|
||||
*/
|
||||
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
|
||||
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.
|
||||
*/
|
||||
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
|
||||
|
||||
/*
|
||||
* Start the SPI driver so that interrupts and the device are enabled.
|
||||
*/
|
||||
XSpi_Start(&Spi);
|
||||
|
||||
/*
|
||||
* Initialize the Serial Flash Library.
|
||||
*/
|
||||
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set The transfer Mode to Interrupt
|
||||
*/
|
||||
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
|
||||
|
||||
/*
|
||||
* Specify the address in the Serial Flash for the Erase/Write/Read
|
||||
* operations.
|
||||
*/
|
||||
Address = ISF_TEST_ADDRESS;
|
||||
|
||||
/*
|
||||
* The following code Erases a Sector in the Winbond Serial Flash.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Sector Erase operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the Quad Enable (QE) bit in the flash device, so that Quad
|
||||
* operations can be perfomed on the flash.
|
||||
*/
|
||||
Status = SpiFlashQuadEnable();
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address within the Serial Flash where the data is to be written.
|
||||
* - Number of bytes to be written to the Serial Flash.
|
||||
* - Write Buffer which contains the data to be written to the Serial
|
||||
* Flash.
|
||||
*/
|
||||
WriteParam.Address = Address;
|
||||
WriteParam.NumBytes = ISF_PAGE_SIZE;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
|
||||
/*
|
||||
* Prepare the write buffer. Fill in the data need to be written into
|
||||
* Serial Flash.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Write(&Isf, XISF_QUAD_IP_PAGE_WRITE, (void*) &WriteParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read from the flash using Dual Output Fast Read command.
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
* - Number of dummy bytes for the read command.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ISF_PAGE_SIZE;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
ReadParam.NumDummyBytes = DUAL_READ_DUMMY_BYTES;
|
||||
|
||||
/*
|
||||
* Clear the read Buffer.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES +
|
||||
DUAL_READ_DUMMY_BYTES; Index++) {
|
||||
ReadBuffer[Index] = 0x0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the read operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Read(&Isf, XISF_DUAL_OP_FAST_READ, (void*) &ReadParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the data read against the data Written.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES +
|
||||
DUAL_READ_DUMMY_BYTES] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable High Performance Mode so that data can be read from the flash
|
||||
* using DIO and QIO read commands.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Ioctl(&Isf, XISF_IOCTL_ENABLE_HI_PERF_MODE);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read from the flash using Dual Input/Output Fast Read command.
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
* - Number of dummy bytes for the read command.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ISF_PAGE_SIZE;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
ReadParam.NumDummyBytes = DUAL_IO_READ_DUMMY_BYTES;
|
||||
|
||||
/*
|
||||
* Clear the read Buffer.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES +
|
||||
DUAL_IO_READ_DUMMY_BYTES; Index++) {
|
||||
ReadBuffer[Index] = 0x0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the read operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Read(&Isf, XISF_DUAL_IO_FAST_READ, (void*) &ReadParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the data read against the data Written.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES +
|
||||
DUAL_IO_READ_DUMMY_BYTES] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read from the flash using Quad Output Fast Read command.
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
* - Number of dummy bytes for the read command.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ISF_PAGE_SIZE;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
ReadParam.NumDummyBytes = QUAD_READ_DUMMY_BYTES;
|
||||
|
||||
/*
|
||||
* Clear the read Buffer.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES +
|
||||
QUAD_READ_DUMMY_BYTES; Index++) {
|
||||
ReadBuffer[Index] = 0x0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the read operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Read(&Isf, XISF_QUAD_OP_FAST_READ, (void*) &ReadParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the data read against the data Written.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES +
|
||||
QUAD_READ_DUMMY_BYTES] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read from the flash using Quad Input/Output Fast Read command.
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
* - Number of dummy bytes for the read command.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ISF_PAGE_SIZE;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
ReadParam.NumDummyBytes = QUAD_IO_READ_DUMMY_BYTES;
|
||||
|
||||
/*
|
||||
* Clear the read Buffer.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES +
|
||||
QUAD_IO_READ_DUMMY_BYTES; Index++) {
|
||||
ReadBuffer[Index] = 0x0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the read operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Read(&Isf, XISF_QUAD_IO_FAST_READ, (void*) &ReadParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the data read against the data written.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES +
|
||||
QUAD_IO_READ_DUMMY_BYTES] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function waits till the Winbond 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 Serial Flash and
|
||||
* waits till the Serial Flash is ready to accept next command.
|
||||
*
|
||||
******************************************************************************/
|
||||
int IsfWaitForFlashNotBusy(void)
|
||||
{
|
||||
int Status;
|
||||
u8 StatusReg;
|
||||
|
||||
while(1) {
|
||||
|
||||
/*
|
||||
* Get the Status Register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_GetStatus(&Isf, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the Serial Flash is ready to accept the next
|
||||
* command. If so break.
|
||||
*/
|
||||
StatusReg = ReadBuffer[BYTE2];
|
||||
if((StatusReg & XISF_SR_IS_READY_MASK) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function sets the QuadEnable bit in Winbond flash.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int SpiFlashQuadEnable(void)
|
||||
{
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare the WriteBuffer.
|
||||
*/
|
||||
WriteBuffer[BYTE1] = 0x00;
|
||||
WriteBuffer[BYTE2] = 0x02; /* QE = 1 */
|
||||
|
||||
/*
|
||||
* Perform the Write operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Write(&Isf, XISF_WRITE_STATUS_REG2, (void*) WriteBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
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 SpiHandler(void *CallBackRef, u32 StatusEvent, u16 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, specify real mode so that
|
||||
* the SPI can cause interrupts through 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;
|
||||
}
|
|
@ -0,0 +1,355 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
* XILINX 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 xilisf_winbond_rdwr_polled_example.c
|
||||
*
|
||||
* This file contains a design example using the In-system and Serial Flash
|
||||
* Library (XilIsf) for Reading/Writing to a Winbond W25QXX/W25XX Serial Flash
|
||||
* Device with the Spi driver in polled mode of operation. This example shows
|
||||
* the Erase, Read and Write features.
|
||||
*
|
||||
* This example
|
||||
* - Erases a Sector
|
||||
* - Writes to a Page within the Erased Sector
|
||||
* - Reads back the Page that is written and compares the data
|
||||
*
|
||||
* This example has been tested with a Winbond Serial Flash Memory (W25Q64) on
|
||||
* a Xilinx SP605 board. For further details about the Flash device refer the
|
||||
* Winbond Serial Flash Memory (W25Q64) data sheet.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- --- -------- -----------------------------------------------
|
||||
* 2.01a sdm 03/17/10 First release
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h" /* EDK generated parameters */
|
||||
#include "xilisf.h" /* Serial Flash Library header file */
|
||||
|
||||
/************************** 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
|
||||
|
||||
/*
|
||||
* 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 ISF_SPI_SELECT 0x01
|
||||
|
||||
/*
|
||||
* Number of bytes per page in the flash device.
|
||||
*/
|
||||
#define ISF_PAGE_SIZE 256
|
||||
|
||||
/*
|
||||
* Address of the page to perform Erase, Write and Read operations.
|
||||
*/
|
||||
#define ISF_TEST_ADDRESS 0x010000;
|
||||
#define ISF_TEST_BYTE 0x36 /* Test Byte offset value written */
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
static int IsfWaitForFlashNotBusy(void);
|
||||
|
||||
/************************** 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 XIsf Isf;
|
||||
static XSpi Spi;
|
||||
|
||||
/*
|
||||
* The user needs to allocate a buffer to be used by the In-system and Serial
|
||||
* Flash Library to perform any read/write operations on the Serial Flash
|
||||
* device.
|
||||
* User applications must pass the address of this memory to the Library in
|
||||
* Serial Flash Initialization function, for the Library to work.
|
||||
* For Write operations:
|
||||
* - The size of this buffer should be equal to the Number of bytes to be
|
||||
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
|
||||
* - The size of this buffer should be large enough for usage across all the
|
||||
* applications that use a common instance of the Serial Flash.
|
||||
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
|
||||
* to the Serial Flash, through a single Write operation.
|
||||
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
|
||||
* application only reads from the Serial Flash (no write operations).
|
||||
*/
|
||||
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
|
||||
|
||||
/*
|
||||
* Buffers used during Read/Write transactions.
|
||||
*/
|
||||
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; /* Read Buffer */
|
||||
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
|
||||
|
||||
/************************** Function Definitions ******************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to execute the Winbond Serial Flash Read/Write polled example.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
******************************************************************************/
|
||||
int main()
|
||||
{
|
||||
int Status;
|
||||
u32 Index;
|
||||
u32 Address;
|
||||
XIsf_WriteParam WriteParam;
|
||||
XIsf_ReadParam ReadParam;
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the SPI driver so that it's ready to use,
|
||||
* specify the device ID that is generated in xparameters.h.
|
||||
*/
|
||||
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the SPI driver so that the device is enabled.
|
||||
*/
|
||||
XSpi_Start(&Spi);
|
||||
|
||||
/*
|
||||
* Disable Global interrupt to use the Spi driver in polled mode
|
||||
* operation.
|
||||
*/
|
||||
XSpi_IntrGlobalDisable(&Spi);
|
||||
|
||||
/*
|
||||
* Initialize the Serial Flash Library.
|
||||
*/
|
||||
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Specify the address in the Serial Flash for the Erase/Write/Read
|
||||
* operations.
|
||||
*/
|
||||
Address = ISF_TEST_ADDRESS;
|
||||
|
||||
/*
|
||||
* The following code Erases a Sector in the Winbond Serial Flash.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Sector Erase operation.
|
||||
*/
|
||||
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address within the Serial Flash where the data is to be written.
|
||||
* - Number of bytes to be written to the Serial Flash.
|
||||
* - Write Buffer which contains the data to be written to the Serial
|
||||
* Flash.
|
||||
*/
|
||||
WriteParam.Address = Address;
|
||||
WriteParam.NumBytes = ISF_PAGE_SIZE;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
|
||||
/*
|
||||
* Prepare the write buffer. Fill in the data need to be written into
|
||||
* Serial Flash.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write operation.
|
||||
*/
|
||||
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ISF_PAGE_SIZE;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
|
||||
/*
|
||||
* Perform the read operation.
|
||||
*/
|
||||
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the data read against the data Written.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function waits till the Winbond 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 Serial Flash and
|
||||
* waits till the Serial Flash is ready to accept next command.
|
||||
*
|
||||
******************************************************************************/
|
||||
int IsfWaitForFlashNotBusy(void)
|
||||
{
|
||||
int Status;
|
||||
u8 StatusReg;
|
||||
|
||||
while(1) {
|
||||
|
||||
/*
|
||||
* Get the Status Register.
|
||||
*/
|
||||
Status = XIsf_GetStatus(&Isf, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the Serial Flash is ready to accept the next
|
||||
* command. If so break.
|
||||
*/
|
||||
StatusReg = ReadBuffer[BYTE2];
|
||||
if((StatusReg & XISF_SR_IS_READY_MASK) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,555 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
* XILINX 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 xilisf_winbond_read_write_example.c
|
||||
*
|
||||
* This file contains a design example using the In-system and Serial Flash
|
||||
* Library (XilIsf) for Reading/Writing to a Winbond W25QXX/W25XX Serial Flash
|
||||
* Device. This example shows the Erase, Read and Write features.
|
||||
*
|
||||
* This example
|
||||
* - Erases a Sector
|
||||
* - Writes to a Page within the Erased Sector
|
||||
* - Reads back the Page that is written and compares the data
|
||||
*
|
||||
* This example has been tested with a Winbond Serial Flash Memory (W25Q64) on
|
||||
* a Xilinx SP605 board. For further details about the Flash device refer the
|
||||
* Winbond Serial Flash Memory (W25Q64) data sheet.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -----------------------------------------------
|
||||
* 2.01a sdm 03/17/10 First release
|
||||
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
|
||||
* instead of driver handler.
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h" /* EDK generated parameters */
|
||||
#include "xintc.h" /* Interrupt controller device driver */
|
||||
#include <xilisf.h> /* Serial Flash Library header file */
|
||||
#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 ISF_SPI_SELECT 0x01
|
||||
|
||||
/*
|
||||
* Number of bytes per page in the flash device.
|
||||
*/
|
||||
#define ISF_PAGE_SIZE 256
|
||||
|
||||
/*
|
||||
* Address of the page to perform Erase, Write and Read operations.
|
||||
*/
|
||||
#define ISF_TEST_ADDRESS 0x010000;
|
||||
#define ISF_TEST_BYTE 0x05 /* Test Byte offset value written */
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
static int IsfWaitForFlashNotBusy(void);
|
||||
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 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 XIsf Isf;
|
||||
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; /* State of Spi Transfer */
|
||||
static int ErrorCount; /* Errors occurred during Spi transfers */
|
||||
|
||||
/*
|
||||
* The user needs to allocate a buffer to be used by the In-system and Serial
|
||||
* Flash Library to perform any read/write operations on the Serial Flash
|
||||
* device.
|
||||
* User applications must pass the address of this memory to the Library in
|
||||
* Serial Flash Initialization function, for the Library to work.
|
||||
* For Write operations:
|
||||
* - The size of this buffer should be equal to the Number of bytes to be
|
||||
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
|
||||
* - The size of this buffer should be large enough for usage across all the
|
||||
* applications that use a common instance of the Serial Flash.
|
||||
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
|
||||
* to the Serial Flash, through a single Write operation.
|
||||
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
|
||||
* application only reads from the Serial Flash (no write operations).
|
||||
*/
|
||||
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
|
||||
|
||||
/*
|
||||
* Buffers used during Read/Write transactions.
|
||||
*/
|
||||
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; /* Read Buffer */
|
||||
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
|
||||
|
||||
/************************** Function Definitions ******************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to execute the Winbond Serial Flash Read/Write example.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
******************************************************************************/
|
||||
int main()
|
||||
{
|
||||
int Status;
|
||||
u32 Index;
|
||||
u32 Address;
|
||||
XIsf_WriteParam WriteParam;
|
||||
XIsf_ReadParam ReadParam;
|
||||
|
||||
/*
|
||||
* Initialize the SPI driver so that it's ready to use,
|
||||
* specify the device ID that is generated in xparameters.h.
|
||||
*/
|
||||
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
|
||||
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.
|
||||
*/
|
||||
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
|
||||
|
||||
/*
|
||||
* Start the SPI driver so that interrupts and the device are enabled.
|
||||
*/
|
||||
XSpi_Start(&Spi);
|
||||
|
||||
/*
|
||||
* Initialize the Serial Flash Library.
|
||||
*/
|
||||
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set The transfer Mode to Interrupt
|
||||
*/
|
||||
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
|
||||
|
||||
/*
|
||||
* Specify the address in the Serial Flash for the Erase/Write/Read
|
||||
* operations.
|
||||
*/
|
||||
Address = ISF_TEST_ADDRESS;
|
||||
|
||||
/*
|
||||
* The following code Erases a Sector in the Winbond Serial Flash.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Sector Erase operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address within the Serial Flash where the data is to be written.
|
||||
* - Number of bytes to be written to the Serial Flash.
|
||||
* - Write Buffer which contains the data to be written to the Serial
|
||||
* Flash.
|
||||
*/
|
||||
WriteParam.Address = Address;
|
||||
WriteParam.NumBytes = ISF_PAGE_SIZE;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
|
||||
/*
|
||||
* Prepare the write buffer. Fill in the data need to be written into
|
||||
* Serial Flash.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ISF_PAGE_SIZE;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
|
||||
/*
|
||||
* Perform the read operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the data read against the data Written.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function waits till the Winbond 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 Serial Flash and
|
||||
* waits till the Serial Flash is ready to accept next command.
|
||||
*
|
||||
******************************************************************************/
|
||||
int IsfWaitForFlashNotBusy(void)
|
||||
{
|
||||
int Status;
|
||||
u8 StatusReg;
|
||||
|
||||
while(1) {
|
||||
|
||||
/*
|
||||
* Get the Status Register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_GetStatus(&Isf, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is complete and check for errors.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the Serial Flash is ready to accept the next
|
||||
* command. If so break.
|
||||
*/
|
||||
StatusReg = ReadBuffer[BYTE2];
|
||||
if((StatusReg & XISF_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, u16 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, specify real mode so that
|
||||
* the SPI can cause interrupts through 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;
|
||||
}
|
754
lib/sw_services/xilisf/examples/xilisf_winbond_spr_example.c
Normal file
754
lib/sw_services/xilisf/examples/xilisf_winbond_spr_example.c
Normal file
|
@ -0,0 +1,754 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
* XILINX 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 xilisf_winbond_spr_example.c
|
||||
*
|
||||
* This file contains a design example using the Xilinx In-system and Serial
|
||||
* Flash Library (XilIsf). This example shows the usage of Sector Erase, Sector
|
||||
* Protection, Read and Write features on a Winbond W25QXX/W25XX Serial Flash
|
||||
* Device.
|
||||
|
||||
* This example
|
||||
* - Erases a Sector
|
||||
* - Writes to a Page within the erased Sector
|
||||
* - Enables the Sector Protection so that all the sectors are Write protected
|
||||
* - Erases a Page (This should not happen as the Sectors are Write protected
|
||||
* - Reads back the Page that is written and compares the data
|
||||
*
|
||||
* This example has been tested with a Winbond Serial Flash Memory (W25Q64) on
|
||||
* a Xilinx SP605 board. For further details about the Flash device refer the
|
||||
* Winbond Serial Flash Memory (W25Q64) data sheet.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -----------------------------------------------
|
||||
* 2.01a sdm 03/17/10 First release
|
||||
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
|
||||
* instead of driver handler.
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h" /* EDK generated parameters */
|
||||
#include "xintc.h" /* Interrupt controller device driver */
|
||||
#include "xspi.h" /* SPI device driver */
|
||||
#include <xilisf.h> /* Serial Flash Library header file */
|
||||
#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 Serial Flash on the SPI bus, this signal is typically
|
||||
* connected to the chip select of the device.
|
||||
*/
|
||||
#define ISF_SPI_SELECT 0x01
|
||||
|
||||
/*
|
||||
* Number of bytes per page in the Serial Flash.
|
||||
*/
|
||||
#define ISF_PAGE_SIZE 256
|
||||
|
||||
/*
|
||||
* Address of the page to perform Erase, Write and Read operations.
|
||||
*/
|
||||
#define ISF_TEST_ADDRESS 0x010000;
|
||||
#define ISF_TEST_BYTE 0x15 /* Test Byte offset value written */
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
static int IsfWaitForFlashNotBusy(void);
|
||||
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 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 XIsf Isf;
|
||||
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.
|
||||
*/
|
||||
static int ErrorCount;
|
||||
|
||||
/*
|
||||
* The user needs to allocate a buffer to be used by the In-system and Serial
|
||||
* Flash Library to perform any read/write operations on the Serial Flash
|
||||
* device.
|
||||
* User applications must pass the address of this memory to the Library in
|
||||
* Serial Flash Initialization function, for the Library to work.
|
||||
* For Write operations:
|
||||
* - The size of this buffer should be equal to the Number of bytes to be
|
||||
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
|
||||
* - The size of this buffer should be large enough for usage across all the
|
||||
* applications that use a common instance of the Serial Flash.
|
||||
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
|
||||
* to the Serial Flash, through a single Write operation.
|
||||
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
|
||||
* application only reads from the Serial Flash (no write operations).
|
||||
*/
|
||||
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
|
||||
|
||||
/*
|
||||
* Buffers used during read and write transactions.
|
||||
*/
|
||||
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
|
||||
u8 WriteBuffer[ISF_PAGE_SIZE];
|
||||
|
||||
/************************** Function Definitions ******************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to execute the Winbond Serial Flash SPR example.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
******************************************************************************/
|
||||
int main()
|
||||
{
|
||||
int Status;
|
||||
u32 Index;
|
||||
u32 Address;
|
||||
XIsf_WriteParam WriteParam;
|
||||
XIsf_ReadParam ReadParam;
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the SPI driver so that it's ready to use,
|
||||
* specify the device ID that is generated in xparameters.h.
|
||||
*/
|
||||
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
|
||||
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.
|
||||
*/
|
||||
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
|
||||
|
||||
/*
|
||||
* Start the SPI driver so that interrupts and the device are enabled.
|
||||
*/
|
||||
XSpi_Start(&Spi);
|
||||
|
||||
/*
|
||||
* Initialize the Serial Flash Library.
|
||||
*/
|
||||
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set The transfer Mode to Interrupt
|
||||
*/
|
||||
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
|
||||
|
||||
/*
|
||||
* Specify the address in the Serial Flash for the Erase/Write/Read
|
||||
* operations.
|
||||
*/
|
||||
Address = ISF_TEST_ADDRESS;
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Sector Erase operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address within the Serial Flash where the data is to be written.
|
||||
* - Number of bytes to be written to the Serial Flash.
|
||||
* - Write Buffer which contains the data to be written to the Serial
|
||||
* Flash.
|
||||
*/
|
||||
WriteParam.Address = Address;
|
||||
WriteParam.NumBytes = ISF_PAGE_SIZE;
|
||||
WriteParam.WritePtr = WriteBuffer;
|
||||
|
||||
/*
|
||||
* Prepare the write buffer. Fill in the data that needs to be written
|
||||
* to the Serial Flash.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the sector protection register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set all the block protection bits in the sector protection register
|
||||
* value read above and write it back to the sector protection register
|
||||
* to disable protection for all sectors.
|
||||
*/
|
||||
WriteBuffer[BYTE1] = ReadBuffer[BYTE2] |
|
||||
(XISF_SR_BLOCK_PROTECT_MASK);
|
||||
|
||||
/*
|
||||
* Enable the sector protection.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Write Enable operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the Sector Erase operation. This should not work as sector
|
||||
* protection is enabled for all the sectors.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the sector protection register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear all the block protection bits in the sector protection register
|
||||
* value read above and write it back to the sector protection register
|
||||
* to disable protection for all sectors.
|
||||
*/
|
||||
WriteBuffer[BYTE1] = ReadBuffer[BYTE2] &
|
||||
~(XISF_SR_BLOCK_PROTECT_MASK);
|
||||
|
||||
/*
|
||||
* Disable the sector protection.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Flash is not Busy.
|
||||
*/
|
||||
Status = IsfWaitForFlashNotBusy();
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the
|
||||
* - Address in the Serial Flash where the data is to be read from.
|
||||
* - Number of bytes to be read from the Serial Flash.
|
||||
* - Read Buffer to which the data is to be read.
|
||||
*/
|
||||
ReadParam.Address = Address;
|
||||
ReadParam.NumBytes = ISF_PAGE_SIZE;
|
||||
ReadParam.ReadPtr = ReadBuffer;
|
||||
|
||||
/*
|
||||
* Perform the Read operation.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
|
||||
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) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the data read against the data written.
|
||||
*/
|
||||
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
|
||||
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
|
||||
(u8)(Index + ISF_TEST_BYTE)) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function waits till the Winbond Serial Flash is ready to accept the next
|
||||
* command.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note This function reads the status register of the Serial Flash and
|
||||
waits till the WIP bit of the status register becomes 0.
|
||||
*
|
||||
******************************************************************************/
|
||||
int IsfWaitForFlashNotBusy(void)
|
||||
{
|
||||
int Status;
|
||||
u8 StatusReg;
|
||||
|
||||
while(1) {
|
||||
|
||||
/*
|
||||
* Get the Status Register.
|
||||
*/
|
||||
TransferInProgress = TRUE;
|
||||
Status = XIsf_GetStatus(&Isf, ReadBuffer);
|
||||
if(Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the Transfer is in progress.
|
||||
*/
|
||||
while(TransferInProgress);
|
||||
|
||||
/*
|
||||
* Check if there are any errors in the transaction.
|
||||
*/
|
||||
if(ErrorCount != 0) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the flash is ready to accept the next command.
|
||||
* If so break.
|
||||
*/
|
||||
StatusReg = ReadBuffer[BYTE2];
|
||||
if((StatusReg & XISF_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, u16 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;
|
||||
}
|
89
lib/sw_services/xilisf/src/Makefile
Normal file
89
lib/sw_services/xilisf/src/Makefile
Normal file
|
@ -0,0 +1,89 @@
|
|||
###############################################################################
|
||||
#
|
||||
# Copyright (C) 2012 - 2015 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
|
||||
# XILINX 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.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
COMPILER=
|
||||
ARCHIVER=
|
||||
CP=cp
|
||||
COMPILER_FLAGS=
|
||||
EXTRA_COMPILER_FLAGS=
|
||||
|
||||
RELEASEDIR=../../../lib
|
||||
INCLUDEDIR=../../../include
|
||||
INCLUDES=-I${INCLUDEDIR}
|
||||
ISF_DIR = .
|
||||
|
||||
LIB_SRCS = $(ISF_DIR)/xilisf.c \
|
||||
$(ISF_DIR)/xilisf_read.c \
|
||||
$(ISF_DIR)/xilisf_erase.c \
|
||||
$(ISF_DIR)/xilisf_write.c \
|
||||
$(ISF_DIR)/xilisf_spr.c
|
||||
|
||||
# create ISF_SRCS based on configured options
|
||||
|
||||
ISF_SRCS = $(LIB_SRCS)
|
||||
|
||||
ISF_OBJS = $(ISF_SRCS:%.c=%.o)
|
||||
|
||||
|
||||
EXPORT_INCLUDE_FILES = $(ISF_DIR)/include/xilisf.h \
|
||||
$(ISF_DIR)/include/xilisf_atmel.h \
|
||||
$(ISF_DIR)/include/xilisf_intelstm.h
|
||||
|
||||
|
||||
libs: libxilisf.a
|
||||
cp libxilisf.a $(RELEASEDIR)
|
||||
make clean
|
||||
|
||||
include:
|
||||
@for i in $(EXPORT_INCLUDE_FILES); do \
|
||||
echo ${CP} -r $$i ${INCLUDEDIR}; \
|
||||
${CP} -r $$i ${INCLUDEDIR}; \
|
||||
done
|
||||
|
||||
clean:
|
||||
rm -rf obj/*.o
|
||||
rmdir obj
|
||||
rm libxilisf.a
|
||||
|
||||
|
||||
libxilisf.a: obj_dir print_msg_isf_base $(ISF_OBJS)
|
||||
@echo "Creating archive $@"
|
||||
$(ARCHIVER) rc $@ obj/*.o
|
||||
|
||||
obj_dir:
|
||||
mkdir obj
|
||||
|
||||
print_msg_isf_base:
|
||||
@echo "Compiling XilIsf Library"
|
||||
|
||||
.c.o:
|
||||
$(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) -c $< -o obj/$(@F)
|
1045
lib/sw_services/xilisf/src/include/xilisf.h
Normal file
1045
lib/sw_services/xilisf/src/include/xilisf.h
Normal file
File diff suppressed because it is too large
Load diff
268
lib/sw_services/xilisf/src/include/xilisf_atmel.h
Normal file
268
lib/sw_services/xilisf/src/include/xilisf_atmel.h
Normal file
|
@ -0,0 +1,268 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 - 2015 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
|
||||
* XILINX 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 xilisf_atmel.h
|
||||
*
|
||||
* This file contains the definitions to be used when accessing the Atmel
|
||||
* AT45XXXD Serial Flash.
|
||||
* If any new definitions are added to this file, check if they need to be
|
||||
* added to the xilisf_intelstm.h file too.
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ------- -------- -----------------------------------------------
|
||||
* 1.00a ksu/sdm 03/03/08 First release
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef XILISF_ATMEL_H /* prevent circular inclusions */
|
||||
#define XILISF_ATMEL_H /* by using protection macros */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
|
||||
/**
|
||||
* The following definitions specify the Device Id for the different Atmel
|
||||
* AT45XXXD Serial Flash Devices.
|
||||
*/
|
||||
#define XISF_ATMEL_DEV_AT45DB011D 0x22 /**< Device ID of AT45DB011D */
|
||||
#define XISF_ATMEL_DEV_AT45DB021D 0x23 /**< Device ID of AT45DB027D */
|
||||
#define XISF_ATMEL_DEV_AT45DB041D 0x24 /**< Device ID of AT45DB041D */
|
||||
#define XISF_ATMEL_DEV_AT45DB081D 0x25 /**< Device ID of AT45DB081D */
|
||||
#define XISF_ATMEL_DEV_AT45DB161D 0x26 /**< Device ID of AT45DB161D */
|
||||
#define XISF_ATMEL_DEV_AT45DB321D 0x27 /**< Device ID of AT45DB321D */
|
||||
#define XISF_ATMEL_DEV_AT45DB642D 0x28 /**< Device ID of AT45DB642D */
|
||||
|
||||
|
||||
/**
|
||||
* Definitions of Atmel Serial Flash Device geometry.
|
||||
*/
|
||||
#define XISF_BYTES256_PER_PAGE 256 /**< 256 Bytes per Page */
|
||||
#define XISF_BYTES264_PER_PAGE 264 /**< 264 Bytes per Page */
|
||||
#define XISF_BYTES512_PER_PAGE 512 /**< 512 Bytes per Page */
|
||||
#define XISF_BYTES528_PER_PAGE 528 /**< 528 Bytes per Page */
|
||||
#define XISF_BYTES1024_PER_PAGE 1024 /**< 1024 Bytes per Page */
|
||||
#define XISF_BYTES1056_PER_PAGE 1056 /**< 1056 Bytes per Page */
|
||||
#define XISF_PAGES8_PER_BLOCK 8 /**< Pages per Block */
|
||||
#define XISF_BLOCKS16_PER_SECTOR 16 /**< 16 Blocks per Sector */
|
||||
#define XISF_BLOCKS32_PER_SECTOR 32 /**< 32 Blocks per Sector */
|
||||
#define XISF_NUM_OF_SECTORS4 4 /**< 4 Sectors */
|
||||
#define XISF_NUM_OF_SECTORS8 8 /**< 8 Sectors */
|
||||
#define XISF_NUM_OF_SECTORS16 16 /**< 16 Sectors */
|
||||
#define XISF_NUM_OF_SECTORS32 32 /**< 32 Sectors */
|
||||
#define XISF_NUM_OF_SECTORS64 64 /**< 64 Sectors */
|
||||
|
||||
/**
|
||||
* Definitions of Bit masks used for calculating device address from a
|
||||
* linear address in the case of Default Addressing mode .
|
||||
*/
|
||||
#define XISF_BYTES256_PER_PAGE_MASK 0x0FF /**< Byte mask for devices with
|
||||
* 256 or less bytes per page
|
||||
*/
|
||||
#define XISF_BYTES512_PER_PAGE_MASK 0x1FF /**< Byte mask for devices with
|
||||
* more than 256 bytes per
|
||||
* page */
|
||||
#define XISF_BYTES1024_PER_PAGE_MASK 0x3FF /**< Byte mask for devices with
|
||||
* more than 512 bytes per
|
||||
* page */
|
||||
#define XISF_BYTES2048_PER_PAGE_MASK 0x7FF /**< Byte mask for devices with
|
||||
* more than 1024 bytes per
|
||||
* page */
|
||||
|
||||
/**
|
||||
* Definitions of Read commands.
|
||||
*/
|
||||
#define XISF_CMD_RANDOM_READ 0x03 /**< Random Read command */
|
||||
#define XISF_CMD_FAST_READ 0x0B /**< Fast Read command */
|
||||
#define XISF_CMD_ISFINFO_READ 0x9F /**< Device Info command */
|
||||
#define XISF_CMD_PAGETOBUF1_TRANS 0x53 /**< Transfer contents of a Page
|
||||
* to the Buffer 1 command */
|
||||
#define XISF_CMD_PAGETOBUF2_TRANS 0x55 /**< Transfer contents of a Page
|
||||
* to the Buffer 2 command */
|
||||
#define XISF_CMD_BUF1_READ 0xD1 /**< Buffer 1 Read command */
|
||||
#define XISF_CMD_BUF2_READ 0xD3 /**< Buffer 2 Read command */
|
||||
#define XISF_CMD_FAST_BUF1_READ 0xD4 /**< Fast Buffer 1 Read Cmd */
|
||||
#define XISF_CMD_FAST_BUF2_READ 0xD6 /**< Fast Buffer 2 Read Cmd */
|
||||
#define XISF_CMD_STATUSREG_READ 0xD7 /**< Status Greg Read Cmd */
|
||||
|
||||
/**
|
||||
* Definitions of Write commands.
|
||||
*/
|
||||
#define XISF_CMD_PAGEPROG_WRITE 0x82 /**< Page Program command */
|
||||
#define XISF_CMD_AUTOPAGE_WRITE 0x58 /**< Auto write command */
|
||||
#define XISF_CMD_BUFFER1_WRITE 0x84 /**< Buffer1 write command */
|
||||
#define XISF_CMD_BUFFER2_WRITE 0x87 /**< Buffer2 write command */
|
||||
#define XISF_CMD_ERASE_BUF1TOPAGE_WRITE 0x83 /**< Erase page first then write
|
||||
* buffer 1 to the page
|
||||
* command */
|
||||
#define XISF_CMD_ERASE_BUF2TOPAGE_WRITE 0x86 /**< Erase page first then write
|
||||
* buffer2 to the page
|
||||
* command */
|
||||
#define XISF_CMD_BUF1TOPAGE_WRITE 0x88 /**< Write buffer1 to the page
|
||||
* command without Erase */
|
||||
#define XISF_CMD_BUF2TOPAGE_WRITE 0x89 /**< Write buffer2 to the page
|
||||
* command without Erase */
|
||||
|
||||
/**
|
||||
* Definitions of Erase commands.
|
||||
*/
|
||||
#define XISF_CMD_PAGE_ERASE 0x81 /**< Page Erase command */
|
||||
#define XISF_CMD_BLOCK_ERASE 0x50 /**< Block erase command */
|
||||
#define XISF_CMD_SECTOR_ERASE 0x7C /**< Sector Erase command */
|
||||
|
||||
/**
|
||||
* Definitions of commands used for
|
||||
* - Erasing SPR
|
||||
* - Programming SPR
|
||||
* - Enabling/Disabling SPR.
|
||||
*/
|
||||
#define XISF_CMD_SPR_BYTE1 0x3D /**< SPR command byte1 */
|
||||
#define XISF_CMD_SPR_BYTE2 0x2A /**< SPR command byte2 */
|
||||
#define XISF_CMD_SPR_BYTE3 0x7F /**< SPR command byte3 */
|
||||
#define XISF_CMD_SPR_BYTE4_ERASE 0xCF /**< SPR erase command */
|
||||
#define XISF_CMD_SPR_BYTE4_PROGRAM 0xFC /**< SPR program command */
|
||||
#define XISF_CMD_SPR_BYTE4_ENABLE 0xA9 /**< SPR enable command */
|
||||
#define XISF_CMD_SPR_BYTE4_DISABLE 0x9A /**< SPR disable command */
|
||||
|
||||
/**
|
||||
* Definitions of command used for reading SPR.
|
||||
*/
|
||||
#define XISF_CMD_SPR_READ 0x32 /**< SPR read command */
|
||||
|
||||
/**
|
||||
* The following definitions specify the buffer number of Atmel Serial Flash.
|
||||
*/
|
||||
#define XISF_PAGE_BUFFER1 1 /**< Buffer 1 */
|
||||
#define XISF_PAGE_BUFFER2 2 /**< Buffer 2 */
|
||||
|
||||
|
||||
/**
|
||||
* The following definitions specify the Status Register bit definitions of
|
||||
* Atmel Serial Flash.
|
||||
*/
|
||||
#define XISF_SR_ADDR_MODE_MASK 0x01 /**< Address mode mask */
|
||||
#define XISF_SR_COMPARE_MASK 0x40 /**< Compare mask */
|
||||
#define XISF_SR_IS_READY_MASK 0x80 /**< Ready mask */
|
||||
#define XISF_SR_DEVID_MASK 0x2C /**< Device ID mask */
|
||||
#define XISF_SR_DEVID_SHIFT_MASK 0x02 /**< Device ID shift mask */
|
||||
|
||||
/**
|
||||
* The following definitions determine the addressing mode of the Atmel Serial
|
||||
* Flash.
|
||||
*/
|
||||
#define XISF_POWEROFTWO_ADDRESS 0x01 /**< Pow-Of-2 address mask */
|
||||
#define XISF_DEFAULT_ADDRESS 0x00 /**< Default address mask */
|
||||
|
||||
/**
|
||||
* This definitions specify the extra bytes in each of the Write command, Read
|
||||
* command, Erase command, commands operating on SPR, auto page write, page to
|
||||
* buffer and buffer to page transfer commands. This count includes
|
||||
* Command byte, address bytes and any don't care bytes needed.
|
||||
*/
|
||||
#define XISF_CMD_SEND_EXTRA_BYTES 4 /**< Command extra bytes */
|
||||
|
||||
/**
|
||||
* This definition specifies the extra bytes in each of the Write/Read/Erase
|
||||
* commands, commands operating on SPR, auto page write, page to
|
||||
* buffer and buffer to page transfer commands in 4 bytes addressing mode.
|
||||
* This count includes Command byte, Address bytes and any
|
||||
* don't care bytes needed.
|
||||
*/
|
||||
#define XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE 5 /**< Command extra bytes */
|
||||
|
||||
/**
|
||||
* This definitions specify the extra bytes in Fast read Fast buffer read
|
||||
* commands. This count includes Command byte, address bytes and any don't care
|
||||
* bytes needed.
|
||||
*/
|
||||
#define XISF_CMD_FAST_READ_EXTRA_BYTES 5 /**< Fast read and Fast buffer
|
||||
* read extra bytes */
|
||||
|
||||
/**
|
||||
* The following definitions specify the total bytes in some of the commands.
|
||||
* This count includes Command byte and any don't care bytes needed.
|
||||
*/
|
||||
#define XISF_STATUS_RDWR_BYTES 2 /**< Status Read/Write bytes
|
||||
* count */
|
||||
#define XISF_INFO_READ_BYTES 5 /**< Flash Info Read bytes
|
||||
* count */
|
||||
#define XISF_INFO_EXTRA_BYTES 1 /**< Flash Info Read Extra
|
||||
* bytes */
|
||||
#define XISF_CMD_MAX_EXTRA_BYTES 5 /**< Max extra bytes for
|
||||
* all commands */
|
||||
#define XISF_DUMMYBYTE 0xFF /**< Dummy byte to fill */
|
||||
|
||||
|
||||
/**
|
||||
* Address Shift Masks.
|
||||
*/
|
||||
#define XISF_ADDR_SHIFT16 16 /**< 16 bit Shift */
|
||||
#define XISF_ADDR_SHIFT8 8 /**< 8 bit Shift */
|
||||
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* end of protection macro */
|
365
lib/sw_services/xilisf/src/include/xilisf_intelstm.h
Normal file
365
lib/sw_services/xilisf/src/include/xilisf_intelstm.h
Normal file
|
@ -0,0 +1,365 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 - 2015 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
|
||||
* XILINX 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 xilisf_intelstm.h
|
||||
*
|
||||
* This file contains the definitions to be used when accessing the Intel, STM,
|
||||
* Winbond and Spansion Serial Flash.
|
||||
* If any new definitions are added to this file, check if they need to be
|
||||
* added to the xilisf_atmel.h file too.
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ------- -------- -----------------------------------------------
|
||||
* 1.00a ksu/sdm 03/03/08 First release
|
||||
* 2.01a sdm 01/04/10 Added Support for Winbond W25QXX/W25XX devices
|
||||
* 2.04a sdm 08/17/10 Updated to support Numonyx (N25QXX) and Spansion
|
||||
* flash memories
|
||||
* 3.00a srt 06/20/12 Updated to support interfaces SPI PS and QSPI PS.
|
||||
* Added support to SST flash on SPI PS interface.
|
||||
* 3.02a srt 04/26/13 Modified SECTOR and BLOCK Erase commands for
|
||||
* SST flash (CR 703816).
|
||||
* 5.2 asa 05/12/15 Added macros for 4 byte commands.
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef XILISF_INTELSTM_H /* prevent circular inclusions */
|
||||
#define XILISF_INTELSTM_H /* by using protection macros */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
|
||||
/**
|
||||
* The following definitions specify the Device Id for the different
|
||||
* Intel (Numonyx) S33 Serial Flash devices.
|
||||
*/
|
||||
#define XISF_INTEL_DEV_S3316MBIT 0x11 /**< Device ID for 16Mbit */
|
||||
#define XISF_INTEL_DEV_S3332MBIT 0x12 /**< Device ID for 32Mbit */
|
||||
#define XISF_INTEL_DEV_S3364MBIT 0x13 /**< Device ID for 64Mbit */
|
||||
|
||||
/**
|
||||
* The following definitions specify the Device Id for the different
|
||||
* STM (Numonyx) M25PXX Serial Flash devices.
|
||||
*/
|
||||
#define XISF_STM_DEV_M25P05_A 0x2010 /**< Device ID for M25P05-A */
|
||||
#define XISF_STM_DEV_M25P10_A 0x2011 /**< Device ID for M25P10-A */
|
||||
#define XISF_STM_DEV_M25P20 0x2012 /**< Device ID for M25P20 */
|
||||
#define XISF_STM_DEV_M25P40 0x2013 /**< Device ID for M25P40 */
|
||||
#define XISF_STM_DEV_M25P80 0x2014 /**< Device ID for M25P80 */
|
||||
#define XISF_STM_DEV_M25P16 0x2015 /**< Device ID for M25P16 */
|
||||
#define XISF_STM_DEV_M25P32 0x2016 /**< Device ID for M25P32 */
|
||||
#define XISF_STM_DEV_M25P64 0x2017 /**< Device ID for M25P64 */
|
||||
#define XISF_STM_DEV_M25P128 0x2018 /**< Device ID for M25P128 */
|
||||
|
||||
/**
|
||||
* The following definitions specify the Device Id (memory type/capacity)
|
||||
* for the different Winbond W25QX/W25XX Serial Flash devices.
|
||||
*/
|
||||
#define XISF_WB_DEV_W25Q80 0x4014 /**< Device ID for W25Q80 */
|
||||
#define XISF_WB_DEV_W25Q16 0x4015 /**< Device ID for W25Q16 */
|
||||
#define XISF_WB_DEV_W25Q32 0x4016 /**< Device ID for W25Q32 */
|
||||
#define XISF_WB_DEV_W25Q64 0x4017 /**< Device ID for W25Q64 */
|
||||
#define XISF_WB_DEV_W25Q128 0x4018 /**< Device ID for W25Q128 */
|
||||
#define XISF_WB_DEV_W25X10 0x3011 /**< Device ID for W25X10 */
|
||||
#define XISF_WB_DEV_W25X20 0x3012 /**< Device ID for W25X20 */
|
||||
#define XISF_WB_DEV_W25X40 0x3013 /**< Device ID for W25X40 */
|
||||
#define XISF_WB_DEV_W25X80 0x3014 /**< Device ID for W25X80 */
|
||||
#define XISF_WB_DEV_W25X16 0x3015 /**< Device ID for W25X16 */
|
||||
#define XISF_WB_DEV_W25X32 0x3016 /**< Device ID for W25X32 */
|
||||
#define XISF_WB_DEV_W25X64 0x3017 /**< Device ID for W25X64 */
|
||||
|
||||
/**
|
||||
* The following definitions specify the Device Id (memory type/capacity)
|
||||
* for the different STM (Numonyx) N25QXX Serial Flash devices.
|
||||
*/
|
||||
#define XISF_NM_DEV_N25Q32 0xBA16 /**< Device ID for N25Q32 */
|
||||
#define XISF_NM_DEV_N25Q64 0xBA17 /**< Device ID for N25Q64 */
|
||||
#define XISF_NM_DEV_N25Q128 0xBA18 /**< Device ID for N25Q128 */
|
||||
#define XISF_MIC_DEV_N25Q128 0xBB18 /**< Device ID for N25Q128 */
|
||||
#define XISF_MIC_DEV_N25Q256_3V0 0xBA19
|
||||
#define XISF_MIC_DEV_N25Q256_1V8 0xBB19
|
||||
|
||||
/**
|
||||
* The following definitions specify the Device Id for the different
|
||||
* Spansion S25FLXX Serial Flash devices.
|
||||
*/
|
||||
#define XISF_SPANSION_DEV_S25FL004 0x0212 /**< Device ID for S25FL004 */
|
||||
#define XISF_SPANSION_DEV_S25FL008 0x0213 /**< Device ID for S25FL008 */
|
||||
#define XISF_SPANSION_DEV_S25FL016 0x0214 /**< Device ID for S25FL016 */
|
||||
#define XISF_SPANSION_DEV_S25FL032 0x0215 /**< Device ID for S25FL032 */
|
||||
#define XISF_SPANSION_DEV_S25FL064 0x0216 /**< Device ID for S25FL064 */
|
||||
#define XISF_SPANSION_DEV_S25FL128 0x2018 /**< Device ID for S25FL128
|
||||
* and S25FL129 */
|
||||
|
||||
/**
|
||||
* The following definitions specify the Device Id for the different
|
||||
* SST Serial Flash device.
|
||||
*/
|
||||
#define XISF_SST_DEV_SST25WF080 0x2505 /**< Device ID for SST25WF080 */
|
||||
|
||||
/**
|
||||
* Definitions for Intel, STM, Winbond and Spansion Serial Flash Device
|
||||
* geometry.
|
||||
*/
|
||||
#define XISF_BYTES256_PER_PAGE 256 /**< 256 Bytes per Page */
|
||||
#define XISF_PAGES16_PER_SECTOR 16 /**< 16 Pages per Sector */
|
||||
#define XISF_PAGES128_PER_SECTOR 128 /**< 128 Pages per Sector */
|
||||
#define XISF_PAGES256_PER_SECTOR 256 /**< 256 Pages per Sector */
|
||||
#define XISF_PAGES1024_PER_SECTOR 1024 /**< 1024 Pages per Sector */
|
||||
#define XISF_NUM_OF_SECTORS2 2 /**< 2 Sectors */
|
||||
#define XISF_NUM_OF_SECTORS4 4 /**< 4 Sectors */
|
||||
#define XISF_NUM_OF_SECTORS8 8 /**< 8 Sector */
|
||||
#define XISF_NUM_OF_SECTORS16 16 /**< 16 Sectors */
|
||||
#define XISF_NUM_OF_SECTORS32 32 /**< 32 Sectors */
|
||||
#define XISF_NUM_OF_SECTORS64 64 /**< 64 Sectors */
|
||||
#define XISF_NUM_OF_SECTORS128 128 /**< 128 Sectors */
|
||||
#define XISF_NUM_OF_SECTORS256 256 /**< 256 Sectors */
|
||||
#define XISF_NUM_OF_SECTORS512 512 /**< 512 Sectors */
|
||||
#define XISF_NUM_OF_SECTORS1024 1024 /**< 1024 Sectors */
|
||||
#define XISF_NUM_OF_SECTORS2048 2048 /**< 2048 Sectors */
|
||||
#define XISF_NUM_OF_SECTORS4096 4096 /**< 4096 Sectors */
|
||||
|
||||
/**
|
||||
* Definitions of Read commands.
|
||||
*/
|
||||
#define XISF_CMD_RANDOM_READ 0x03 /**< Random Read command */
|
||||
#define XISF_CMD_RANDOM_READ_4BYTE 0x13 /**< Random 4 byte Read command */
|
||||
#define XISF_CMD_FAST_READ 0x0B /**< Fast Read command */
|
||||
#define XISF_CMD_FAST_READ_4BYTE 0x0C /**< 4 byte Fast Read command */
|
||||
#define XISF_CMD_ISFINFO_READ 0x9F /**< Device Info command */
|
||||
#define XISF_CMD_STATUSREG_READ 0x05 /**< Status Reg Read command */
|
||||
#define XISF_CMD_STATUSREG2_READ 0x35 /**< Status Reg2 Read command */
|
||||
#define XISF_CMD_DUAL_OP_FAST_READ 0x3B /**< Dual output fast read */
|
||||
#define XISF_CMD_DUAL_OP_FAST_READ_4B 0x3C /**< 4 byte Dual output fast read */
|
||||
#define XISF_CMD_DUAL_IO_FAST_READ 0xBB /**< Dual i/o fast read */
|
||||
#define XISF_CMD_DUAL_IO_FAST_READ_4B 0xBC /**< 4 byte Dual i/o fast read */
|
||||
#define XISF_CMD_QUAD_OP_FAST_READ 0x6B /**< Quad output fast read */
|
||||
#define XISF_CMD_QUAD_OP_FAST_READ_4B 0x6C /**< 4 byte Quad output fast read */
|
||||
#define XISF_CMD_QUAD_IO_FAST_READ 0xEB /**< Quad i/o fast read */
|
||||
#define XISF_CMD_QUAD_IO_FAST_READ_4B 0xEC /**< 4 byte Quad i/o fast read */
|
||||
|
||||
/**
|
||||
* Definitions of Write commands.
|
||||
*/
|
||||
#define XISF_CMD_PAGEPROG_WRITE 0x02 /**< Page Program command */
|
||||
#define XISF_CMD_PAGEPROG_WRITE_4BYTE 0x12 /**< 4 byte Page Program command */
|
||||
#define XISF_CMD_STATUSREG_WRITE 0x01 /**< Status Reg Write Command */
|
||||
#define XISF_CMD_DUAL_IP_PAGE_WRITE 0xA2 /**< Dual input fast page write
|
||||
*/
|
||||
#define XISF_CMD_DUAL_IP_EXT_PAGE_WRITE 0xD2 /**< Dual input extended fast
|
||||
* page write */
|
||||
#define XISF_CMD_QUAD_IP_PAGE_WRITE 0x32 /**< Quad input fast page write
|
||||
*/
|
||||
#define XISF_CMD_QUAD_IP_EXT_PAGE_WRITE 0x12 /**< Dual input extended fast
|
||||
* page write */
|
||||
|
||||
/**
|
||||
* Definitions of Erase commands.
|
||||
*/
|
||||
#define XISF_CMD_BULK_ERASE 0xC7 /**< Bulk Erase command */
|
||||
|
||||
|
||||
#if ((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) || \
|
||||
(XPAR_XISF_FLASH_FAMILY == SPANSION))
|
||||
#define XISF_CMD_SECTOR_ERASE 0xD8 /**< Sector Erase command */
|
||||
#define XISF_CMD_SUB_SECTOR_ERASE 0x20 /**< Sub-sector Erase command.
|
||||
* only for N25QXX */
|
||||
#define XISF_CMD_4BYTE_SECTOR_ERASE 0xDC
|
||||
#endif /* ((XPAR_XISF_FLASH_FAMILY==INTEL)||(XPAR_XISF_FLASH_FAMILY == STM) ||
|
||||
(XPAR_XISF_FLASH_FAMILY == SPANSION)) */
|
||||
|
||||
#if ((XPAR_XISF_FLASH_FAMILY == WINBOND) || (XPAR_XISF_FLASH_FAMILY == SST))
|
||||
#define XISF_CMD_BLOCK_ERASE 0xD8 /**< Block Erase command */
|
||||
#define XISF_CMD_SECTOR_ERASE 0x20 /**< Sector Erase command */
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Definitions of commands used for
|
||||
* - Write Enable/Disable.
|
||||
* - Deep Power Down mode Enter/Release.
|
||||
* - Switch to 4 byte addressing
|
||||
*/
|
||||
#define XISF_CMD_ENABLE_WRITE 0x06 /**< Write enable command */
|
||||
#define XISF_CMD_DISABLE_WRITE 0x04 /**< Write disable command */
|
||||
#define XISF_CMD_DEEP_POWER_DOWN 0xB9 /**< Enter DPD mode command */
|
||||
#define XISF_CMD_RELEASE_FROM_DPD 0xAB /**< Release DPD mode command */
|
||||
|
||||
#define XISF_CMD_ENABLE_HPM 0xA3 /**< Enable high performance
|
||||
* mode */
|
||||
|
||||
#if (XPAR_XISF_FLASH_FAMILY == SPANSION)
|
||||
#define XISF_CMD_ENTER_4BYTE_ADDR_MODE 0xB7
|
||||
#define XISF_CMD_EXIT_4BYTE_ADDR_MODE 0xE9
|
||||
#endif
|
||||
#if (XPAR_XISF_FLASH_FAMILY == INTEL)
|
||||
/**
|
||||
* Definitions of commands which are only supported in Intel Serial Flash.
|
||||
*/
|
||||
#define XISF_CMD_OTP_READ 0x4B /**< OTP data read command */
|
||||
#define XISF_CMD_OTP_WRITE 0x42 /**< OTP write command */
|
||||
#define XISF_CMD_PARAM_BLOCK_ERASE 0x40 /**< Parameter Block Erase
|
||||
* command */
|
||||
#define XISF_CMD_CLEAR_SRFAIL_FLAGS 0x30 /**< Clear SR fail bits Cmd */
|
||||
#define XISF_OTP_RDWR_EXTRA_BYTES 0x05 /**< OTP Read/Write
|
||||
* extra bytes */
|
||||
#endif /* INTEL */
|
||||
|
||||
|
||||
/**
|
||||
* The following definitions specify the Status Register bit definitions of
|
||||
* Intel, STM, Winbond and Spansion Serial Flash.
|
||||
*/
|
||||
#define XISF_SR_IS_READY_MASK 0x01 /**< Ready mask */
|
||||
#define XISF_SR_WRITE_ENABLE_MASK 0x02 /**< Write Enable latch mask */
|
||||
#define XISF_SR_BLOCK_PROTECT_MASK 0x1C /**< Block Protect mask */
|
||||
#define XISF_SR_WRITE_PROTECT_MASK 0x80 /**< Status Reg write
|
||||
* protect mask */
|
||||
#define XISF_SR_BLOCK_PROTECT_SHIFT 2 /**< Block protect bits shift */
|
||||
|
||||
#if (XPAR_XISF_FLASH_FAMILY == INTEL)
|
||||
#define XISF_SR_PROG_FAIL_MASK 0x40 /**< Program Fail bit mask */
|
||||
#define XISF_SR_ERASE_FAIL_MASK 0x20 /**< Erase Fail bit mask */
|
||||
#endif /* (XPAR_XISF_FLASH_FAMILY == INTEL) */
|
||||
|
||||
#if (XPAR_XISF_FLASH_FAMILY == WINBOND)
|
||||
#define XISF_SR_TB_PROTECT_MASK 0x20 /**< Top/Bottom Write Protect */
|
||||
#define XISF_SR_SECTOR_PROTECT_MASK 0x40 /**< Sector Protect mask */
|
||||
#endif /* (XPAR_XISF_FLASH_FAMILY == WINBOND) */
|
||||
|
||||
|
||||
/**
|
||||
* The definition specifies the total bytes in Bulk Erase commands.
|
||||
* This count includes Command byte and any don't care bytes needed.
|
||||
*/
|
||||
#define XISF_BULK_ERASE_BYTES 0x01 /**< Bulk erase extra bytes */
|
||||
|
||||
/**
|
||||
* The following definitions specify the Write Enable and Disable operation
|
||||
* arguments to be passed to the XIsf_WriteEnable API.
|
||||
*/
|
||||
#define XISF_WRITE_ENABLE 1 /**< Write enable */
|
||||
#define XISF_WRITE_DISABLE 0 /**< Write disable */
|
||||
|
||||
/**
|
||||
* This definition specifies the extra bytes in each of the Write Enable/Disable
|
||||
* commands. This count includes Command byte, address bytes and any don't care
|
||||
* bytes needed.
|
||||
*/
|
||||
#define XISF_CMD_WRITE_ENABLE_DISABLE_BYTES 1 /**< Write enable/disable
|
||||
* command extra bytes */
|
||||
|
||||
/**
|
||||
* This definition specifies the extra bytes in 4 byte addr mode enter and exit
|
||||
* commands. This count refers to the Command byte.
|
||||
*/
|
||||
#define XISF_CMD_4BYTE_ADDR_ENTER_EXIT_BYTES 1 /**< Four byte addr mode
|
||||
* command extra bytes */
|
||||
/**
|
||||
* This definition specifies the extra bytes in each of the Write/Read/Erase
|
||||
* commands, commands operating on SPR, auto page write, page to
|
||||
* buffer and buffer to page transfer commands. This count includes
|
||||
* Command byte, Address bytes and any don't care bytes needed.
|
||||
*/
|
||||
#define XISF_CMD_SEND_EXTRA_BYTES 4 /**< Command extra bytes */
|
||||
|
||||
/**
|
||||
* This definition specifies the extra bytes in each of the Write/Read/Erase
|
||||
* commands, commands operating on SPR, auto page write, page to
|
||||
* buffer and buffer to page transfer commands in 4 bytes addressing mode.
|
||||
* This count includes Command byte, Address bytes and any
|
||||
* don't care bytes needed.
|
||||
*/
|
||||
#define XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE 5 /**< Command extra bytes */
|
||||
|
||||
/**
|
||||
* This definition specifies the extra bytes in Fast Read and Fast Buffer Read
|
||||
* commands. This count includes Command byte, address bytes and any don't care
|
||||
* bytes needed.
|
||||
*/
|
||||
#define XISF_CMD_FAST_READ_EXTRA_BYTES 5 /**< Fast read and Fast buffer
|
||||
* read extra bytes */
|
||||
|
||||
/**
|
||||
* The following definitions specify the total bytes in some of the commands.
|
||||
* This count includes Command byte and any don't care bytes needed.
|
||||
*/
|
||||
#define XISF_STATUS_RDWR_BYTES 2 /**< Status Read/Write bytes
|
||||
* count */
|
||||
#define XISF_INFO_READ_BYTES 5 /**< Serial Flash Info read
|
||||
* bytes count */
|
||||
#define XISF_INFO_EXTRA_BYTES 1 /**< Serial Flash Info extra
|
||||
* bytes */
|
||||
#define XISF_IOCTL_BYTES 1 /**< Serial Flash IOCTL bytes */
|
||||
#define XISF_HPM_BYTES 4 /**< Serial Flash HPM bytes */
|
||||
#define XISF_CMD_MAX_EXTRA_BYTES 5 /**< Max extra bytes for
|
||||
* all commands */
|
||||
#define XISF_DUMMYBYTE 0xFF /**< Dummy byte to fill */
|
||||
|
||||
/**
|
||||
* Address Shift Masks.
|
||||
*/
|
||||
#define XISF_ADDR_SHIFT24 24 /**< 24 bit Shift */
|
||||
#define XISF_ADDR_SHIFT16 16 /**< 16 bit Shift */
|
||||
#define XISF_ADDR_SHIFT8 8 /**< 8 bit Shift */
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* end of protection macro */
|
1956
lib/sw_services/xilisf/src/xilisf.c
Normal file
1956
lib/sw_services/xilisf/src/xilisf.c
Normal file
File diff suppressed because it is too large
Load diff
597
lib/sw_services/xilisf/src/xilisf_erase.c
Normal file
597
lib/sw_services/xilisf/src/xilisf_erase.c
Normal file
|
@ -0,0 +1,597 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 - 2015 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
|
||||
* XILINX 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 xilisf_erase.c
|
||||
*
|
||||
* This file contains the library functions to Erase the Serial Flash.
|
||||
* Refer xilisf.h for a detailed description.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ------- -------- -----------------------------------------------
|
||||
* 1.00a ksu/sdm 03/03/08 First release
|
||||
* 2.01a sdm 01/04/10 Added Support for Winbond W25QXX/W25XX devices
|
||||
* 2.04a sdm 08/17/10 Updated to support Numonyx (N25QXX) and Spansion
|
||||
* flash memories
|
||||
* 3.02a srt 04/25/13 Added Bulk Erase command support for SST and
|
||||
* Spansion flashes.
|
||||
* 5.0 sb 08/05/14 Updated support for > 128 MB flash for PSQSPI
|
||||
* interface.
|
||||
* New API:
|
||||
* DieErase()
|
||||
* Changed API:
|
||||
* SectorErase()
|
||||
* BulkErase()
|
||||
* 5.2 asa 05/12/15 Added support for Micron (N25Q256A) flash part
|
||||
* which supports 4 byte addressing.
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "include/xilisf.h"
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
#define SIXTEENMB 0x1000000 /**< Sixteen MB */
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
extern int XIsf_Transfer(XIsf *InstancePtr, u8 *WritePtr, u8* ReadPtr,
|
||||
u32 ByteCount);
|
||||
extern u32 GetRealAddr(XIsf_Iface *QspiPtr, u32 Address);
|
||||
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
||||
extern int SendBankSelect(XIsf *InstancePtr, u32 BankSel);
|
||||
#endif
|
||||
static int PageErase(XIsf *InstancePtr, u32 Address);
|
||||
static int BlockErase(XIsf *InstancePtr, u32 Address);
|
||||
static int SectorErase(XIsf *InstancePtr, u32 Address);
|
||||
static int BulkErase(XIsf *InstancePtr);
|
||||
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
||||
static int DieErase(XIsf *InstancePtr);
|
||||
#endif
|
||||
/************************** Variable Definitions *****************************/
|
||||
extern u32 XIsf_StatusEventInfo;
|
||||
extern unsigned int XIsf_ByteCountInfo;
|
||||
/************************** Function Definitions ******************************/
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This API erases the contents of the specified memory in the Serial Flash.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param Operation is the type of Erase operation to be performed on the
|
||||
* Serial Flash.
|
||||
* The different operations are
|
||||
* - XISF_PAGE_ERASE: Page Erase
|
||||
* - XISF_BLOCK_ERASE: Block Erase
|
||||
* - XISF_SECTOR_ERASE: Sector Erase
|
||||
- XISF_BULK_ERASE: Bulk Erase
|
||||
* @param Address is the address of the Page/Block/Sector to be erased.
|
||||
* The address can be either Page address, Block address or Sector
|
||||
* address based on the Erase operation to be performed.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
* - The erased bytes will read as 0xFF.
|
||||
* - For Intel, STM, Winbond or Spansion Serial Flash the user
|
||||
* application must call XIsf_WriteEnable() API by passing
|
||||
* XISF_WRITE_ENABLE as an argument before calling XIsf_Erase()
|
||||
* API.
|
||||
* - Atmel Serial Flash support Page/Block/Sector Erase
|
||||
- operations.
|
||||
* - Intel, Winbond, Numonyx (N25QXX) and Spansion Serial Flash
|
||||
* support Sector/Block/Bulk Erase operations.
|
||||
* - STM (M25PXX) Serial Flash support Sector/Bulk Erase
|
||||
* operations.
|
||||
*
|
||||
******************************************************************************/
|
||||
int XIsf_Erase(XIsf *InstancePtr, XIsf_EraseOperation Operation, u32 Address)
|
||||
{
|
||||
int Status = (int)(XST_FAILURE);
|
||||
u8 Mode;
|
||||
|
||||
if (InstancePtr == NULL) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
if (InstancePtr->IsReady != TRUE) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
switch (Operation) {
|
||||
|
||||
case XISF_PAGE_ERASE:
|
||||
Status = PageErase(InstancePtr, Address);
|
||||
break;
|
||||
|
||||
case XISF_BLOCK_ERASE:
|
||||
Status = BlockErase(InstancePtr, Address);
|
||||
break;
|
||||
|
||||
case XISF_SECTOR_ERASE:
|
||||
Status = SectorErase(InstancePtr, Address);
|
||||
break;
|
||||
|
||||
case XISF_BULK_ERASE:
|
||||
Status = BulkErase(InstancePtr);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get the Transfer Mode
|
||||
*/
|
||||
Mode = XIsf_GetTransferMode(InstancePtr);
|
||||
|
||||
if(Mode == XISF_INTERRUPT_MODE){
|
||||
InstancePtr->StatusHandler(InstancePtr,
|
||||
XIsf_StatusEventInfo, XIsf_ByteCountInfo);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function erases the contents of the specified Page in the Serial Flash.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param Address is the address of Page to be erased. This can be any
|
||||
* address in the Page to be erased. The Byte address values in
|
||||
* this address are ignored.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
* - The erased bytes will read as 0xFF.
|
||||
* - This operation is only supported for Atmel Serial Flash.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int PageErase(XIsf *InstancePtr, u32 Address)
|
||||
{
|
||||
int Status = (int)(XST_FAILURE);
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
Xil_AssertNonvoid(Address != 0);
|
||||
|
||||
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
|
||||
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_PAGE_ERASE;
|
||||
InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16);
|
||||
InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8);
|
||||
InstancePtr->WriteBufPtr[BYTE4] = (u8) XISF_DUMMYBYTE;
|
||||
|
||||
/*
|
||||
* Initiate the Transfer.
|
||||
*/
|
||||
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr,
|
||||
NULL, XISF_CMD_SEND_EXTRA_BYTES);
|
||||
if (Status != (int)(XST_SUCCESS)) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function erases the contents of the specified Block in the Serial Flash.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param Address is the address of the Block to be erased. This can be
|
||||
* any address in the Block to be erased. The Page/Byte address
|
||||
* values in this address are ignored.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
* - The erased bytes will read as 0xFF.
|
||||
* - This operation is supported for Atmel, Intel, Winbond,
|
||||
* Numonyx (N25QXX), and Spansion Serial Flash.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int BlockErase(XIsf *InstancePtr, u32 Address)
|
||||
{
|
||||
int Status = (int)(XST_FAILURE);
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
Xil_AssertNonvoid(Address != 0);
|
||||
|
||||
#if ((XPAR_XISF_FLASH_FAMILY == ATMEL) || (XPAR_XISF_FLASH_FAMILY == INTEL) \
|
||||
|| (XPAR_XISF_FLASH_FAMILY == WINBOND))
|
||||
|
||||
#if ((XPAR_XISF_FLASH_FAMILY == ATMEL) || (XPAR_XISF_FLASH_FAMILY == WINBOND))
|
||||
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BLOCK_ERASE;
|
||||
|
||||
#else
|
||||
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_PARAM_BLOCK_ERASE;
|
||||
|
||||
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
|
||||
|
||||
InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16);
|
||||
InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8);
|
||||
InstancePtr->WriteBufPtr[BYTE4] = (u8) XISF_DUMMYBYTE;
|
||||
|
||||
/*
|
||||
* Initiate the Transfer.
|
||||
*/
|
||||
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr,
|
||||
NULL, XISF_CMD_SEND_EXTRA_BYTES);
|
||||
if (Status != (int)(XST_SUCCESS)) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
#endif /* ((XPAR_XISF_FLASH_FAMILY==ATMEL)||(XPAR_XISF_FLASH_FAMILY==INTEL)) */
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function erases the contents of the specified Sector in Serial Flash.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param Address is the address of the Sector to be erased. This can be
|
||||
* any address in the Sector to be erased.
|
||||
* The Block/Page/Byte address values in this address are ignored.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
* - The erased bytes will read as 0xFF.
|
||||
* - This operation is supported for Atmel, Intel, STM, Winbond
|
||||
* and Spansion Serial Flash.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int SectorErase(XIsf *InstancePtr, u32 Address)
|
||||
{
|
||||
int Status = (int)(XST_FAILURE);
|
||||
u8 Mode;
|
||||
u32 BankSel;
|
||||
u32 RealAddr;
|
||||
u8* NULLPtr = NULL;
|
||||
u8 FlagStatus[2] = {0};
|
||||
u8 FlashStatus[2] = {0};
|
||||
u8 ReadStatusCmdBuf[] = { READ_STATUS_CMD, 0 };
|
||||
u8 ReadFlagSRCmd[] = {READ_FLAG_STATUS_CMD, 0};
|
||||
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
||||
u32 FlashMake = InstancePtr->ManufacturerID;
|
||||
#endif
|
||||
|
||||
Xil_AssertNonvoid(NULLPtr == NULL);
|
||||
|
||||
/*
|
||||
* Translate address based on type of connection
|
||||
* If stacked assert the slave select based on address
|
||||
*/
|
||||
RealAddr = GetRealAddr(InstancePtr->SpiInstPtr, Address);
|
||||
|
||||
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
||||
/*
|
||||
* Initial bank selection
|
||||
*/
|
||||
if(InstancePtr->DeviceIDMemSize > 0x18U) {
|
||||
|
||||
/*
|
||||
* Get the Transfer Mode
|
||||
*/
|
||||
Mode = XIsf_GetTransferMode(InstancePtr);
|
||||
|
||||
/*
|
||||
* Seting the transfer mode to Polled Mode before
|
||||
* performing the Bank Select operation.
|
||||
*/
|
||||
XIsf_SetTransferMode(InstancePtr, XISF_POLLING_MODE);
|
||||
|
||||
/*
|
||||
* Calculate initial bank
|
||||
*/
|
||||
BankSel = RealAddr/SIXTEENMB;
|
||||
/*
|
||||
* Select bank
|
||||
*/
|
||||
Status = SendBankSelect(InstancePtr, BankSel);
|
||||
|
||||
/*
|
||||
* Restoring the transfer mode back
|
||||
*/
|
||||
XIsf_SetTransferMode(InstancePtr, Mode);
|
||||
|
||||
if(Status!=(int)(XST_SUCCESS)){
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \
|
||||
(!defined(XPAR_XISF_INTERFACE_PSQSPI)))
|
||||
if (InstancePtr->FourByteAddrMode == TRUE) {
|
||||
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SECTOR_ERASE;
|
||||
InstancePtr->WriteBufPtr[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT24);
|
||||
InstancePtr->WriteBufPtr[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT16);
|
||||
InstancePtr->WriteBufPtr[BYTE4] = (u8) (RealAddr >> XISF_ADDR_SHIFT8);
|
||||
InstancePtr->WriteBufPtr[BYTE5] = (u8) (RealAddr);
|
||||
} else {
|
||||
#endif
|
||||
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SECTOR_ERASE;
|
||||
InstancePtr->WriteBufPtr[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT16);
|
||||
InstancePtr->WriteBufPtr[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT8);
|
||||
InstancePtr->WriteBufPtr[BYTE4] = (u8) (RealAddr);
|
||||
#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \
|
||||
(!defined(XPAR_XISF_INTERFACE_PSQSPI)))
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
||||
/*
|
||||
* Enable write before transfer
|
||||
*/
|
||||
Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE);
|
||||
if (Status != (int)XST_SUCCESS) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
#endif
|
||||
if (InstancePtr->FourByteAddrMode == TRUE) {
|
||||
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr,
|
||||
NULLPtr, XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE);
|
||||
} else {
|
||||
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr,
|
||||
NULLPtr, XISF_CMD_SEND_EXTRA_BYTES);
|
||||
}
|
||||
if (Status != (int)XST_SUCCESS) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
||||
if((InstancePtr->NumDie > (u8)1) &&
|
||||
(FlashMake == (u32)XISF_MANUFACTURER_ID_MICRON)) {
|
||||
|
||||
Status = XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus,
|
||||
(u32)sizeof(ReadFlagSRCmd));
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for the sector erase command to the Flash to be completed
|
||||
*/
|
||||
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
|
||||
*/
|
||||
Status = XIsf_Transfer(InstancePtr, ReadStatusCmdBuf,
|
||||
FlashStatus,
|
||||
(u32)sizeof(ReadStatusCmdBuf));
|
||||
|
||||
/*
|
||||
* If the status indicates the write is done, then 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 ((FlashStatus[1] & 0x01) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if((InstancePtr->NumDie > (u8)1) &&
|
||||
(FlashMake == (u32)XISF_MANUFACTURER_ID_MICRON)) {
|
||||
|
||||
Status =
|
||||
XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus,
|
||||
(u32)sizeof(ReadFlagSRCmd));
|
||||
}
|
||||
#endif
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function erases the content of an entire Serial Flash.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
* - The erased bytes will read as 0xFF.
|
||||
* - This operation is supported for Intel, STM, Winbond,
|
||||
* Spansion and SST Serial Flashes.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int BulkErase(XIsf *InstancePtr)
|
||||
{
|
||||
int Status = (int)(XST_FAILURE);
|
||||
u8* NULLPtr = NULL;
|
||||
|
||||
#if ((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) || \
|
||||
(XPAR_XISF_FLASH_FAMILY == WINBOND) || (XPAR_XISF_FLASH_FAMILY == SST) \
|
||||
|| (XPAR_XISF_FLASH_FAMILY == SPANSION))
|
||||
|
||||
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
||||
/*
|
||||
* If the number of die is greater than 1 call die erase
|
||||
*/
|
||||
if(InstancePtr->NumDie > 1){
|
||||
Status = DieErase(InstancePtr);
|
||||
}
|
||||
|
||||
else{
|
||||
#endif
|
||||
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BULK_ERASE;
|
||||
|
||||
/*
|
||||
* Enable write before transfer
|
||||
*/
|
||||
Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE);
|
||||
if (Status != (int)XST_SUCCESS) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
|
||||
Xil_AssertNonvoid(NULLPtr == NULL);
|
||||
|
||||
/*
|
||||
* Initiate the Transfer.
|
||||
*/
|
||||
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr,
|
||||
NULLPtr, XISF_BULK_ERASE_BYTES);
|
||||
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
||||
}
|
||||
#endif
|
||||
#endif /* ((XPAR_XISF_FLASH_FAMILY==INTEL)||(XPAR_XISF_FLASH_FAMILY==STM)) \
|
||||
(XPAR_XISF_FLASH_FAMILY == WINBOND) ||
|
||||
(XPAR_XISF_FLASH_FAMILY == SST) ||
|
||||
(XPAR_XISF_FLASH_FAMILY == SPANSION)) */
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function erases the content of a Die of Serial Flash.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
* - This operation is supported for Winbond,
|
||||
* Spansion and Micron Serial Flashes.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int DieErase(XIsf *InstancePtr)
|
||||
{
|
||||
int Status = (int)(XST_FAILURE);
|
||||
u8* NULLPtr = NULL;
|
||||
#if ((XPAR_XISF_FLASH_FAMILY == WINBOND) || \
|
||||
(XPAR_XISF_FLASH_FAMILY == SPANSION))
|
||||
|
||||
u8 DieCnt;
|
||||
u8 ReadFlagSRCmd[] = { READ_FLAG_STATUS_CMD, 0 };
|
||||
u8 FlagStatus[2] = {0};
|
||||
|
||||
for(DieCnt = 0; DieCnt < InstancePtr->NumDie; DieCnt++) {
|
||||
/*
|
||||
* Select bank - the lower of the 2 banks in each die
|
||||
* This is specific to Micron flash
|
||||
*/
|
||||
Status = SendBankSelect(InstancePtr, DieCnt*2);
|
||||
|
||||
/*
|
||||
* Setup the write command with the specified address and data
|
||||
* for the Flash
|
||||
*/
|
||||
/*
|
||||
* This ensures 3B address is sent to flash even with address
|
||||
* greater than 128Mb.
|
||||
* The address is the start address of die - MSB bits will be
|
||||
* derived from bank select by the flash
|
||||
*/
|
||||
InstancePtr->WriteBufPtr[BYTE1] = DIE_ERASE_CMD;
|
||||
InstancePtr->WriteBufPtr[BYTE2] = 0x00;
|
||||
InstancePtr->WriteBufPtr[BYTE3] = 0x00;
|
||||
InstancePtr->WriteBufPtr[BYTE4] = 0x00;
|
||||
|
||||
/*
|
||||
* Enable write before transfer
|
||||
*/
|
||||
Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE);
|
||||
if (Status != (int)XST_SUCCESS) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
|
||||
Xil_AssertNonvoid(NULLPtr == NULL);
|
||||
|
||||
/*
|
||||
* Send the sector erase command and address; no receive buffer
|
||||
* is specified since there is nothing to receive
|
||||
*/
|
||||
Status =
|
||||
XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr,
|
||||
DIE_ERASE_SIZE);
|
||||
|
||||
/*
|
||||
* Wait for the sector erase command to Flash to be completed
|
||||
*/
|
||||
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
|
||||
*/
|
||||
Status =
|
||||
XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus,
|
||||
(u32)sizeof(ReadFlagSRCmd));
|
||||
|
||||
/*
|
||||
* If the status indicates the write is done, then 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 ((FlagStatus[1] & (u8)0x80) == (u8)0x80) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* ((XPAR_XISF_FLASH_FAMILY == WINBOND) || \
|
||||
(XPAR_XISF_FLASH_FAMILY == SPANSION)) */
|
||||
|
||||
return Status;
|
||||
}
|
||||
#endif
|
978
lib/sw_services/xilisf/src/xilisf_read.c
Normal file
978
lib/sw_services/xilisf/src/xilisf_read.c
Normal file
|
@ -0,0 +1,978 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 - 2015 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
|
||||
* XILINX 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 xilisf_read.c
|
||||
*
|
||||
* This file contains the library functions to read data from the Serial Flash
|
||||
* devices. Refer xilisf.h for detailed description.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ------- -------- -----------------------------------------------
|
||||
* 1.00a ksu/sdm 03/03/08 First release
|
||||
* 2.01a sdm 01/04/10 Added Support for Winbond W25QXX/W25XX devices
|
||||
* 2.04a sdm 08/17/10 Updated to support Numonyx (N25QXX) and Spansion
|
||||
* flash memories
|
||||
* 5.0 sb 08/05/14 Updated support for > 128 MB flash for PSQSPI
|
||||
* interface.
|
||||
* Changed API:
|
||||
* ReadData()
|
||||
* FastReadData()
|
||||
*
|
||||
* 5.2 asa 05/12/15 Added support for Micron (N25Q256A) flash part
|
||||
* which supports 4 byte addressing.
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "include/xilisf.h"
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
|
||||
#define FAST_READ_NUM_DUMMY_BYTES 1
|
||||
#define SIXTEENMB 0x1000000 /**< Sixteen MB */
|
||||
#define BANKMASK 0xF000000 /**< Bank mask */
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
extern int XIsf_Transfer(XIsf *InstancePtr, u8 *WritePtr, u8* ReadPtr,
|
||||
u32 ByteCount);
|
||||
extern u32 GetRealAddr(XIsf_Iface *QspiPtr, u32 Address);
|
||||
|
||||
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
||||
extern int SendBankSelect(XIsf *InstancePtr, u32 BankSel);
|
||||
#endif
|
||||
|
||||
static int ReadData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr,
|
||||
u32 ByteCount);
|
||||
static int FastReadData(XIsf *InstancePtr, u8 Command, u32 Address,
|
||||
u8 *ReadPtr,
|
||||
u32 ByteCount, int NumDummyBytes);
|
||||
static int FlashToBufTransfer(XIsf *InstancePtr, u8 BufferNum, u32 Address);
|
||||
static int BufferRead(XIsf *InstancePtr, u8 BufferNum, u8 *ReadPtr,
|
||||
u32 ByteOffset, u32 NumBytes);
|
||||
static int FastBufferRead(XIsf *InstancePtr, u8 BufferNum, u8 *ReadPtr,
|
||||
u32 ByteOffset, u32 NumBytes);
|
||||
static int ReadOTPData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr,
|
||||
u32 ByteCount);
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
extern u32 XIsf_StatusEventInfo;
|
||||
extern unsigned int XIsf_ByteCountInfo;
|
||||
/************************** Function Definitions ******************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This API reads the data from the Serial Flash.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param Operation is the type of the read operation to be performed on
|
||||
* the Serial Flash.
|
||||
* The different operations are
|
||||
- XISF_READ: Normal Read
|
||||
* - XISF_FAST_READ: Fast Read
|
||||
* - XISF_PAGE_TO_BUF_TRANS: Page to Buffer Transfer
|
||||
* - XISF_BUFFER_READ: Buffer Read
|
||||
* - XISF_FAST_BUFFER_READ: Fast Buffer Read
|
||||
* - XISF_OTP_READ: One Time Programmable Area (OTP) Read
|
||||
* - XISF_DUAL_OP_FAST_READ: Dual Output Fast Read
|
||||
* - XISF_DUAL_IO_FAST_READ: Dual Input/Output Fast Read
|
||||
* - XISF_QUAD_OP_FAST_READ: Quad Output Fast Read
|
||||
* - XISF_QUAD_IO_FAST_READ: Quad Input/Output Fast Read
|
||||
* @param OpParamPtr is the pointer to structure variable which contains
|
||||
* operational parameter of specified Operation. This parameter
|
||||
* type is dependant on the type of Operation to be performed.
|
||||
*
|
||||
* - Normal Read (XISF_READ), Fast Read (XISF_FAST_READ),
|
||||
* One Time Programmable Area Read(XISF_OTP_READ), Dual Output
|
||||
* Fast Read (XISF_CMD_DUAL_OP_FAST_READ), Dual Input/Output
|
||||
* Fast Read (XISF_CMD_DUAL_IO_FAST_READ), Quad Output Fast Read
|
||||
* (XISF_CMD_QUAD_OP_FAST_READ) and Quad Input/Output Fast Read
|
||||
* (XISF_CMD_QUAD_IO_FAST_READ):
|
||||
* The OpParamPtr must be of type struct XIsf_ReadParam.
|
||||
* OpParamPtr->Address is start address in the Serial Flash.
|
||||
* OpParamPtr->ReadPtr is a pointer to the memory where the data
|
||||
* read from the Serial Flash is stored.
|
||||
* OpParamPtr->NumBytes is number of bytes to read.
|
||||
* OpParamPtr->NumDummyBytes is the number of dummy bytes to be
|
||||
* transmitted for the Read command. This parameter is only used
|
||||
* in case of Dual and Quad reads.
|
||||
* Normal Read and Fast Read operations are supported for Atmel,
|
||||
* Intel, STM, Winbond and Spansion Serial Flash.
|
||||
* Dual and quad reads are supported for Winbond (W25QXX), Numonyx
|
||||
* (N25QXX) and Spansion (S25FL129) quad flash.
|
||||
* OTP Read operation is only supported in Intel Serial Flash.
|
||||
*
|
||||
* - Page To Buffer Transfer (XISF_PAGE_TO_BUF_TRANS):
|
||||
* The OpParamPtr must be of type struct
|
||||
* XIsf_FlashToBufTransferParam .
|
||||
* OpParamPtr->BufferNum specifies the internal SRAM Buffer of
|
||||
* the Serial Flash. The valid values are XISF_PAGE_BUFFER1
|
||||
* or XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case
|
||||
* of AT45DB011D Flash as it contains a single buffer.
|
||||
* OpParamPtr->Address is start address in the Serial Flash.
|
||||
* This operation is only supported in Atmel Serial Flash.
|
||||
*
|
||||
* - Buffer Read (XISF_BUFFER_READ) and Fast Buffer Read
|
||||
* (XISF_FAST_BUFFER_READ):
|
||||
* The OpParamPtr must be of type struct XIsf_BufferReadParam.
|
||||
* OpParamPtr->BufferNum specifies the internal SRAM Buffer of
|
||||
* the Serial Flash. The valid values are XISF_PAGE_BUFFER1
|
||||
* or XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case of
|
||||
* AT45DB011D Flash as it contains a single buffer.
|
||||
* OpParamPtr->ReadPtr is pointer to the memory where data read
|
||||
* from the SRAM buffer is to be stored.
|
||||
* OpParamPtr->ByteOffset is byte offset in the SRAM buffer from
|
||||
* where the first byte is read.
|
||||
* OpParamPtr->NumBytes is the number of bytes to be read from the
|
||||
* Buffer.
|
||||
* These operations are supported only in Atmel Serial Flash.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
* - Application must fill the structure elements of the third
|
||||
* argument and pass its pointer by type casting it with void
|
||||
* pointer.
|
||||
* - The valid data is available from the fourth location pointed
|
||||
* to by the ReadPtr for Normal Read and Buffer Read operations.
|
||||
* - The valid data is available from fifth location pointed to
|
||||
* by the ReadPtr for Fast Read, Fast Buffer Read and OTP Read
|
||||
* operations.
|
||||
* - The valid data is available from the (4 + NumDummyBytes)th
|
||||
* location pointed to by ReadPtr for Dual/Quad Read operations.
|
||||
*
|
||||
******************************************************************************/
|
||||
int XIsf_Read(XIsf *InstancePtr, XIsf_ReadOperation Operation,
|
||||
void *OpParamPtr)
|
||||
{
|
||||
int Status = (int)(XST_FAILURE);
|
||||
u8 Mode;
|
||||
XIsf_ReadParam *ReadParamPtr;
|
||||
XIsf_FlashToBufTransferParam *FlashToBufTransferParamPtr;
|
||||
XIsf_BufferReadParam *BufferReadParamPtr;
|
||||
|
||||
if (InstancePtr == NULL) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
if (InstancePtr->IsReady != TRUE) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
if (NULL == OpParamPtr) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
switch (Operation) {
|
||||
case XISF_READ:
|
||||
ReadParamPtr = (XIsf_ReadParam*) OpParamPtr;
|
||||
Status = ReadData(InstancePtr,
|
||||
ReadParamPtr->Address,
|
||||
ReadParamPtr->ReadPtr,
|
||||
ReadParamPtr->NumBytes);
|
||||
break;
|
||||
|
||||
case XISF_FAST_READ:
|
||||
ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr;
|
||||
Xil_AssertNonvoid(ReadParamPtr != NULL);
|
||||
Status = FastReadData(InstancePtr,
|
||||
XISF_CMD_FAST_READ,
|
||||
ReadParamPtr->Address,
|
||||
ReadParamPtr->ReadPtr,
|
||||
ReadParamPtr->NumBytes,
|
||||
ReadParamPtr->NumDummyBytes);
|
||||
break;
|
||||
|
||||
case XISF_PAGE_TO_BUF_TRANS:
|
||||
FlashToBufTransferParamPtr =
|
||||
(XIsf_FlashToBufTransferParam*)(void *) OpParamPtr;
|
||||
Xil_AssertNonvoid(FlashToBufTransferParamPtr != NULL);
|
||||
Status = FlashToBufTransfer(InstancePtr,
|
||||
FlashToBufTransferParamPtr->BufferNum,
|
||||
FlashToBufTransferParamPtr->Address);
|
||||
break;
|
||||
|
||||
case XISF_BUFFER_READ:
|
||||
BufferReadParamPtr =
|
||||
(XIsf_BufferReadParam*)(void *) OpParamPtr;
|
||||
Xil_AssertNonvoid(BufferReadParamPtr != NULL);
|
||||
Status = BufferRead(InstancePtr,
|
||||
BufferReadParamPtr->BufferNum,
|
||||
BufferReadParamPtr->ReadPtr,
|
||||
BufferReadParamPtr->ByteOffset,
|
||||
BufferReadParamPtr->NumBytes);
|
||||
break;
|
||||
|
||||
case XISF_FAST_BUFFER_READ:
|
||||
BufferReadParamPtr =
|
||||
(XIsf_BufferReadParam*)(void *) OpParamPtr;
|
||||
Xil_AssertNonvoid(BufferReadParamPtr != NULL);
|
||||
Status = FastBufferRead(InstancePtr,
|
||||
BufferReadParamPtr->BufferNum,
|
||||
BufferReadParamPtr->ReadPtr,
|
||||
BufferReadParamPtr->ByteOffset,
|
||||
BufferReadParamPtr->NumBytes);
|
||||
break;
|
||||
|
||||
case XISF_OTP_READ:
|
||||
ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr;
|
||||
Xil_AssertNonvoid(ReadParamPtr != NULL);
|
||||
Status = ReadOTPData(InstancePtr,
|
||||
ReadParamPtr->Address,
|
||||
ReadParamPtr->ReadPtr,
|
||||
ReadParamPtr->NumBytes);
|
||||
break;
|
||||
|
||||
#if ((XPAR_XISF_FLASH_FAMILY == WINBOND) || (XPAR_XISF_FLASH_FAMILY == STM) \
|
||||
|| (XPAR_XISF_FLASH_FAMILY == SPANSION))
|
||||
case XISF_DUAL_OP_FAST_READ:
|
||||
ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr;
|
||||
Xil_AssertNonvoid(ReadParamPtr != NULL);
|
||||
Status = FastReadData(InstancePtr,
|
||||
XISF_CMD_DUAL_OP_FAST_READ,
|
||||
ReadParamPtr->Address,
|
||||
ReadParamPtr->ReadPtr,
|
||||
ReadParamPtr->NumBytes,
|
||||
ReadParamPtr->NumDummyBytes);
|
||||
break;
|
||||
|
||||
case XISF_DUAL_IO_FAST_READ:
|
||||
ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr;
|
||||
Xil_AssertNonvoid(ReadParamPtr != NULL);
|
||||
Status = FastReadData(InstancePtr,
|
||||
XISF_CMD_DUAL_IO_FAST_READ,
|
||||
ReadParamPtr->Address,
|
||||
ReadParamPtr->ReadPtr,
|
||||
ReadParamPtr->NumBytes,
|
||||
ReadParamPtr->NumDummyBytes);
|
||||
break;
|
||||
|
||||
case XISF_QUAD_OP_FAST_READ:
|
||||
ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr;
|
||||
Xil_AssertNonvoid(ReadParamPtr != NULL);
|
||||
Status = FastReadData(InstancePtr,
|
||||
XISF_CMD_QUAD_OP_FAST_READ,
|
||||
ReadParamPtr->Address,
|
||||
ReadParamPtr->ReadPtr,
|
||||
ReadParamPtr->NumBytes,
|
||||
ReadParamPtr->NumDummyBytes);
|
||||
break;
|
||||
|
||||
case XISF_QUAD_IO_FAST_READ:
|
||||
ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr;
|
||||
Xil_AssertNonvoid(ReadParamPtr != NULL);
|
||||
Status = FastReadData(InstancePtr,
|
||||
XISF_CMD_QUAD_IO_FAST_READ,
|
||||
ReadParamPtr->Address,
|
||||
ReadParamPtr->ReadPtr,
|
||||
ReadParamPtr->NumBytes,
|
||||
ReadParamPtr->NumDummyBytes);
|
||||
break;
|
||||
#endif /*((XPAR_XISF_FLASH_FAMILY == WINBOND) ||
|
||||
(XPAR_XISF_FLASH_FAMILY == STM) ||
|
||||
(XPAR_XISF_FLASH_FAMILY == SPANSION))*/
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the Transfer Mode
|
||||
*/
|
||||
Mode = XIsf_GetTransferMode(InstancePtr);
|
||||
|
||||
if(Mode == XISF_INTERRUPT_MODE){
|
||||
InstancePtr->StatusHandler(InstancePtr,
|
||||
XIsf_StatusEventInfo, XIsf_ByteCountInfo);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function reads data from the Serial Flash.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param Address is the starting address in the Serial Flash from where
|
||||
* the data is to be read.
|
||||
* @param ReadPtr is a pointer to the memory where the data read from
|
||||
* the Serial Flash is stored.
|
||||
* @param ByteCount is the number of bytes to be read from the Serial
|
||||
* Flash.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
* - This operation is supported for Atmel, Intel, STM, Winbond
|
||||
* and Spansion Serial Flash.
|
||||
* - Minimum of one byte and a maximum of an entire Serial Flash
|
||||
* Array can be read.
|
||||
* - The valid data is available from the fourth location pointed
|
||||
* to by the ReadPtr.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int ReadData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr, u32 ByteCount)
|
||||
{
|
||||
u8 Mode;
|
||||
u32 BankSel;
|
||||
u32 RealAddr;
|
||||
int Status;
|
||||
u32 RealByteCnt;
|
||||
u32 BufferIndex;
|
||||
u8 ShiftSize;
|
||||
u32 TotalByteCnt = ByteCount;
|
||||
u32 LocalByteCnt = ByteCount;
|
||||
u32 LocalAddress = Address;
|
||||
u8 WriteBuffer[10] = {0};
|
||||
if (LocalByteCnt <= 0 ) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
|
||||
if (ReadPtr == NULL) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
|
||||
while(((s32)(LocalByteCnt)) > 0) {
|
||||
|
||||
/*
|
||||
* Translate address based on type of connection
|
||||
* If stacked assert the slave select based on address
|
||||
*/
|
||||
RealAddr = GetRealAddr(InstancePtr->SpiInstPtr, LocalAddress);
|
||||
|
||||
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
||||
if(InstancePtr->DeviceIDMemSize > 0x18U) {
|
||||
|
||||
/*
|
||||
* Get the Transfer Mode
|
||||
*/
|
||||
Mode = XIsf_GetTransferMode(InstancePtr);
|
||||
|
||||
/*
|
||||
* Seting the transfer mode to Polled Mode before
|
||||
* performing the Bank Select operation.
|
||||
*/
|
||||
XIsf_SetTransferMode(InstancePtr, XISF_POLLING_MODE);
|
||||
|
||||
BankSel = RealAddr/SIXTEENMB;
|
||||
|
||||
(void)SendBankSelect(InstancePtr, BankSel);
|
||||
|
||||
/*
|
||||
* Restoring the transfer mode back
|
||||
*/
|
||||
XIsf_SetTransferMode(InstancePtr, Mode);
|
||||
}
|
||||
|
||||
/*
|
||||
* If data to be read spans beyond the current bank, then
|
||||
* calculate RealByteCnt in current bank. Else
|
||||
* RealByteCnt is the same as ByteCount
|
||||
*/
|
||||
if((RealAddr & BANKMASK) != ((RealAddr+LocalByteCnt) & BANKMASK)) {
|
||||
RealByteCnt = ((RealAddr & BANKMASK) + SIXTEENMB) - RealAddr;
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
RealByteCnt = LocalByteCnt;
|
||||
|
||||
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
||||
}
|
||||
#endif
|
||||
#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \
|
||||
(!defined(XPAR_XISF_INTERFACE_PSQSPI)))
|
||||
if (InstancePtr->FourByteAddrMode == TRUE) {
|
||||
WriteBuffer[BYTE1] = XISF_CMD_RANDOM_READ_4BYTE;
|
||||
WriteBuffer[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT24);
|
||||
WriteBuffer[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT16);
|
||||
WriteBuffer[BYTE4] = (u8) (RealAddr >> XISF_ADDR_SHIFT8);
|
||||
WriteBuffer[BYTE5] = (u8) (RealAddr);
|
||||
} else {
|
||||
#endif
|
||||
WriteBuffer[BYTE1] = XISF_CMD_RANDOM_READ;
|
||||
WriteBuffer[BYTE2] = (u8)((RealAddr & 0xFF0000) >> XISF_ADDR_SHIFT16);
|
||||
WriteBuffer[BYTE3] = (u8)((RealAddr & 0xFF00) >> XISF_ADDR_SHIFT8);
|
||||
WriteBuffer[BYTE4] = (u8)(RealAddr & 0xFF);
|
||||
#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \
|
||||
(!defined(XPAR_XISF_INTERFACE_PSQSPI)))
|
||||
}
|
||||
#endif
|
||||
if (InstancePtr->FourByteAddrMode == TRUE) {
|
||||
Status = XIsf_Transfer(InstancePtr, WriteBuffer,
|
||||
&(ReadPtr[TotalByteCnt - LocalByteCnt]),
|
||||
RealByteCnt + XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE);
|
||||
} else {
|
||||
Status = XIsf_Transfer(InstancePtr, WriteBuffer,
|
||||
&(ReadPtr[TotalByteCnt - LocalByteCnt]),
|
||||
RealByteCnt + XISF_CMD_SEND_EXTRA_BYTES);
|
||||
}
|
||||
if (Status != (int)(XST_SUCCESS)) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
||||
/*
|
||||
* To discard the first 4 dummy bytes, shift the data in read buffer
|
||||
*/
|
||||
ShiftSize = XISF_CMD_SEND_EXTRA_BYTES;
|
||||
BufferIndex = (TotalByteCnt - LocalByteCnt);
|
||||
for(;
|
||||
BufferIndex < ((TotalByteCnt - LocalByteCnt) + RealByteCnt);
|
||||
BufferIndex++) {
|
||||
ReadPtr[BufferIndex] = ReadPtr[BufferIndex + ShiftSize];
|
||||
}
|
||||
|
||||
/*
|
||||
* Increase address to next bank
|
||||
*/
|
||||
LocalAddress = (LocalAddress & BANKMASK) + SIXTEENMB;
|
||||
#endif
|
||||
/*
|
||||
* Decrease byte count by bytes already read.
|
||||
*/
|
||||
LocalByteCnt = LocalByteCnt - RealByteCnt;
|
||||
|
||||
}
|
||||
|
||||
return (int)XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function reads data from the Serial Flash at a higher speed than normal
|
||||
* Read operation.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param Command is the fast read command used to read data from the
|
||||
* flash. It could be one of XISF_CMD_DUAL/QUAD_*_FAST_READ or
|
||||
* XISF_CMD_FAST_READ.
|
||||
* @param Address is the starting address in the Serial Flash from where
|
||||
* the data is to be read.
|
||||
* @param ReadPtr is a pointer to the memory where the data read from
|
||||
* the Serial Flash is stored.
|
||||
* @param ByteCount is the number of bytes to be read from the Serial
|
||||
* Flash.
|
||||
* @param NumDummyBytes is the number of dummy bytes associated with the
|
||||
* fast read commands.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
* - XISF_CMD_FAST_READ operation is supported for Atmel, Intel,
|
||||
* STM, Winbond and Spansion Serial Flash.
|
||||
* - XISF_CMD_DUAL/QUAD_*_FAST_READ operations are supported on
|
||||
* Winbond (W25QXX), Numonyx (N25QXX) and Spansion (S25FL129)
|
||||
* quad flash devices.
|
||||
* - Minimum of one byte and a maximum of an entire Serial Flash
|
||||
* Array can be read.
|
||||
* - The valid data is available from the (4 + NumDummyBytes)th
|
||||
* location pointed to by the ReadPtr.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int FastReadData(XIsf *InstancePtr, u8 Command, u32 Address,
|
||||
u8 *ReadPtr, u32 ByteCount, int NumDummyBytes)
|
||||
{
|
||||
u8 Mode;
|
||||
int Index;
|
||||
int Status;
|
||||
u32 BankSel;
|
||||
u32 RealAddr;
|
||||
u32 RealByteCnt;
|
||||
u32 BufferIndex;
|
||||
u8 ShiftSize;
|
||||
u32 TotalByteCnt = ByteCount;
|
||||
u32 LocalByteCnt = ByteCount;
|
||||
u32 LocalAddress = Address;
|
||||
u8 WriteBuffer[5]= {0};
|
||||
|
||||
if (LocalByteCnt <= 0 ) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
|
||||
if (ReadPtr == NULL) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
if (NumDummyBytes <= 0) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
while(((s32)(LocalByteCnt)) > 0) {
|
||||
|
||||
/*
|
||||
* Translate address based on type of connection
|
||||
* If stacked assert the slave select based on address
|
||||
*/
|
||||
RealAddr = GetRealAddr(InstancePtr->SpiInstPtr, LocalAddress);
|
||||
|
||||
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
||||
if(InstancePtr->DeviceIDMemSize > 0x18U) {
|
||||
/*
|
||||
* Get the Transfer Mode
|
||||
*/
|
||||
Mode = XIsf_GetTransferMode(InstancePtr);
|
||||
|
||||
/*
|
||||
* Seting the transfer mode to Polled Mode before
|
||||
* performing the Bank Select operation.
|
||||
*/
|
||||
XIsf_SetTransferMode(InstancePtr, XISF_POLLING_MODE);
|
||||
|
||||
BankSel = RealAddr/SIXTEENMB;
|
||||
|
||||
(void)SendBankSelect(InstancePtr, BankSel);
|
||||
|
||||
/*
|
||||
* Restoring the transfer mode back
|
||||
*/
|
||||
XIsf_SetTransferMode(InstancePtr, Mode);
|
||||
}
|
||||
|
||||
/*
|
||||
* If data to be read spans beyond the current bank, then
|
||||
* calculate RealByteCnt in current bank. Else
|
||||
* RealByteCnt is the same as ByteCount
|
||||
*/
|
||||
if((RealAddr & BANKMASK) != ((RealAddr+LocalByteCnt) & BANKMASK)) {
|
||||
RealByteCnt = ((RealAddr & BANKMASK) + SIXTEENMB) - RealAddr;
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
RealByteCnt = LocalByteCnt;
|
||||
|
||||
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
||||
}
|
||||
#endif
|
||||
#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \
|
||||
(!defined(XPAR_XISF_INTERFACE_PSQSPI)))
|
||||
if (InstancePtr->FourByteAddrMode == TRUE) {
|
||||
WriteBuffer[BYTE1] = Command;
|
||||
WriteBuffer[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT24);
|
||||
WriteBuffer[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT16);
|
||||
WriteBuffer[BYTE4] = (u8) (RealAddr >> XISF_ADDR_SHIFT8);
|
||||
WriteBuffer[BYTE5] = (u8) RealAddr;
|
||||
|
||||
for (Index = 0; Index < NumDummyBytes; Index++) {
|
||||
WriteBuffer[Index + BYTE5 + 1] = (u8) (XISF_DUMMYBYTE);
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
WriteBuffer[BYTE1] = Command;
|
||||
WriteBuffer[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT16);
|
||||
WriteBuffer[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT8);
|
||||
WriteBuffer[BYTE4] = (u8) RealAddr;
|
||||
|
||||
for (Index = 0; Index < NumDummyBytes; Index++) {
|
||||
WriteBuffer[Index + BYTE5] = (u8) (XISF_DUMMYBYTE);
|
||||
}
|
||||
#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \
|
||||
(!defined(XPAR_XISF_INTERFACE_PSQSPI)))
|
||||
}
|
||||
#endif
|
||||
RealByteCnt += NumDummyBytes;
|
||||
if (InstancePtr->FourByteAddrMode == TRUE) {
|
||||
Status = (int)XIsf_Transfer(InstancePtr, WriteBuffer,
|
||||
&(ReadPtr[TotalByteCnt - LocalByteCnt]),
|
||||
RealByteCnt + XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE);
|
||||
} else {
|
||||
Status = (int)XIsf_Transfer(InstancePtr, WriteBuffer,
|
||||
&(ReadPtr[TotalByteCnt - LocalByteCnt]),
|
||||
RealByteCnt + XISF_CMD_SEND_EXTRA_BYTES);
|
||||
}
|
||||
if (Status != (int)(XST_SUCCESS)) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
||||
/*
|
||||
* To discard the first 5 dummy bytes, shift the data in read buffer
|
||||
*/
|
||||
ShiftSize = XISF_CMD_SEND_EXTRA_BYTES + (u8)NumDummyBytes;
|
||||
BufferIndex = (TotalByteCnt - LocalByteCnt);
|
||||
for(;
|
||||
BufferIndex < ((TotalByteCnt - LocalByteCnt) + RealByteCnt);
|
||||
BufferIndex++) {
|
||||
ReadPtr[BufferIndex] = ReadPtr[BufferIndex + ShiftSize];
|
||||
}
|
||||
|
||||
/*
|
||||
* Increase address to next bank
|
||||
*/
|
||||
LocalAddress = (LocalAddress & BANKMASK) + SIXTEENMB;
|
||||
#endif
|
||||
/*
|
||||
* Decrease byte count by bytes already read.
|
||||
*/
|
||||
LocalByteCnt = LocalByteCnt - (RealByteCnt - NumDummyBytes);
|
||||
}
|
||||
|
||||
return (int)XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function copies the data from the Serial Flash to the specified SRAM
|
||||
* buffer.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param BufferNum specifies the internal SRAM Buffer to which the data
|
||||
* from Serial Flash is to be transferred. The valid values are
|
||||
* XISF_PAGE_BUFFER1 or XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is
|
||||
* not valid in the case of AT45DB011D Flash as it contains a
|
||||
* single buffer.
|
||||
* @param Address specifies any address within the Page of the Serial
|
||||
* Flash from where the Page of data is to be copied.
|
||||
* Byte address in this Address is ignored as an entire Page of
|
||||
* data is transferred/copied.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
* - This operation is only supported in Atmel Serial Flash.
|
||||
* - This function reads one complete Page from the Serial Flash.
|
||||
* - Read the Spartan-3AN In-system Flash User Guide/Atmel
|
||||
* AT45XXXD Data sheets for more information.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int FlashToBufTransfer(XIsf *InstancePtr, u8 BufferNum, u32 Address)
|
||||
{
|
||||
int Status = (int)(XST_FAILURE);
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
Xil_AssertNonvoid(Address != 0);
|
||||
Xil_AssertNonvoid(BufferNum != 0);
|
||||
|
||||
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
|
||||
/*
|
||||
* Check whether the buffer number is valid or not.
|
||||
*/
|
||||
if ((BufferNum == XISF_PAGE_BUFFER1) ||
|
||||
(BufferNum == XISF_PAGE_BUFFER2)) {
|
||||
if ((InstancePtr->DeviceCode == XISF_ATMEL_DEV_AT45DB011D) &&
|
||||
(BufferNum != XISF_PAGE_BUFFER1)) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
} else {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
if (BufferNum == XISF_PAGE_BUFFER1) {
|
||||
/*
|
||||
* Page to Buffer 1 Transfer.
|
||||
*/
|
||||
InstancePtr->WriteBufPtr[BYTE1] =
|
||||
XISF_CMD_PAGETOBUF1_TRANS;
|
||||
} else {
|
||||
/*
|
||||
* Page to Buffer 2 Transfer.
|
||||
*/
|
||||
InstancePtr->WriteBufPtr[BYTE1] =
|
||||
XISF_CMD_PAGETOBUF2_TRANS;
|
||||
}
|
||||
|
||||
InstancePtr->WriteBufPtr[BYTE2] = (u8)(Address >> XISF_ADDR_SHIFT16);
|
||||
InstancePtr->WriteBufPtr[BYTE3] = (u8)(Address >> XISF_ADDR_SHIFT8);
|
||||
InstancePtr->WriteBufPtr[BYTE4] = (u8)(XISF_DUMMYBYTE);
|
||||
|
||||
/*
|
||||
* Initiate the Transfer.
|
||||
*/
|
||||
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
|
||||
XISF_CMD_SEND_EXTRA_BYTES);
|
||||
if (Status != (int)(XST_SUCCESS)) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
|
||||
|
||||
return Status;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function reads the data available in the SRAM buffer of Serial Flash.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param BufferNum specifies the internal SRAM Buffer from which data
|
||||
* is to be read. The valid values are XISF_PAGE_BUFFER1 or
|
||||
* XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case of
|
||||
* AT45DB011D Flash as it contains a single buffer.
|
||||
* @param ReadPtr is a pointer to the memory where the data read from the
|
||||
* SRAM buffer is stored.
|
||||
* @param ByteOffset is the byte offset in the buffer from where the
|
||||
* first byte is read.
|
||||
* @param NumBytes is the number of bytes to be read from the Buffer.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
* - This operation is only supported in Atmel Serial Flash.
|
||||
* - This function reads a Minimum of one Byte and a Maximum of an
|
||||
* entire SRAM buffer (1 Page) from the Serial Flash.
|
||||
* - The valid data is available from the fourth location pointed
|
||||
* to by the ReadPtr.
|
||||
* - Read the Spartan-3AN In-system Flash User Guide/Atmel
|
||||
* AT45XXXD Data sheets for more information.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int BufferRead(XIsf *InstancePtr, u8 BufferNum, u8 *ReadPtr,
|
||||
u32 ByteOffset, u32 NumBytes)
|
||||
{
|
||||
int Status = (int)(XST_FAILURE);
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
Xil_AssertNonvoid(BufferNum != 0);
|
||||
Xil_AssertNonvoid(ReadPtr != NULL);
|
||||
Xil_AssertNonvoid(ByteOffset != 0);
|
||||
Xil_AssertNonvoid(NumBytes != 0);
|
||||
|
||||
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
|
||||
|
||||
/*
|
||||
* Check if the buffer number is valid or not.
|
||||
*/
|
||||
if ((BufferNum == XISF_PAGE_BUFFER1) ||
|
||||
(BufferNum == XISF_PAGE_BUFFER2)) {
|
||||
if ((InstancePtr->DeviceCode == XISF_ATMEL_DEV_AT45DB011D) &&
|
||||
(BufferNum != XISF_PAGE_BUFFER1)) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
} else {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
if (ReadPtr == NULL) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
if (ByteOffset > InstancePtr->BytesPerPage){
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
if ((NumBytes <= 0) || (NumBytes > InstancePtr->BytesPerPage)) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
if (BufferNum == XISF_PAGE_BUFFER1) {
|
||||
ReadPtr[BYTE1] = XISF_CMD_BUF1_READ; /* Buffer 1 Read. */
|
||||
} else {
|
||||
ReadPtr[BYTE1] = XISF_CMD_BUF2_READ; /* Buffer 2 Read.*/
|
||||
}
|
||||
ReadPtr[BYTE2] = (u8) (0x00);
|
||||
ReadPtr[BYTE3] = (u8) (ByteOffset >> XISF_ADDR_SHIFT8);
|
||||
ReadPtr[BYTE4] = (u8) ByteOffset;
|
||||
|
||||
/*
|
||||
* Initiate the Transfer.
|
||||
*/
|
||||
Status = XIsf_Transfer(InstancePtr, ReadPtr, ReadPtr,
|
||||
NumBytes + XISF_CMD_SEND_EXTRA_BYTES);
|
||||
if (Status != (int)(XST_SUCCESS)) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
|
||||
|
||||
return Status;
|
||||
|
||||
}
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function reads the data from the internal SRAM page buffer of the Serial
|
||||
* Flash memory at higher speed than normal Buffer Read operation.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param BufferNum specifies the internal SRAM Buffer from which data
|
||||
* is to be read. The valid values are XISF_PAGE_BUFFER1 or
|
||||
* XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case of
|
||||
* AT45DB011D Flash as it contains a single buffer.
|
||||
* @param ReadPtr is a pointer to the memory where the data read from the
|
||||
* SRAM buffer is stored.
|
||||
* @param ByteOffset is the byte offset in the buffer from where the
|
||||
* first byte is read.
|
||||
* @param NumBytes is the number of bytes to be read from the Buffer.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
* - This operation is only supported in Atmel Serial Flash.
|
||||
* - This function reads a Minimum of one Byte and a Maximum of an
|
||||
* entire SRAM buffer (1 Page) from the Serial Flash.
|
||||
* - The valid data is available from the fifth location pointed
|
||||
* to by the ReadPtr.
|
||||
* - Read the Spartan-3AN In-system Flash User Guide/Atmel
|
||||
* AT45XXXD Data sheets for more information.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int FastBufferRead(XIsf *InstancePtr, u8 BufferNum, u8 *ReadPtr,
|
||||
u32 ByteOffset, u32 NumBytes)
|
||||
{
|
||||
int Status = (int)(XST_FAILURE);
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
Xil_AssertNonvoid(BufferNum != 0);
|
||||
Xil_AssertNonvoid(ReadPtr != NULL);
|
||||
Xil_AssertNonvoid(ByteOffset != 0);
|
||||
Xil_AssertNonvoid(NumBytes != 0);
|
||||
|
||||
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
|
||||
/*
|
||||
* Check if the buffer number is valid or not.
|
||||
*/
|
||||
if ((BufferNum == XISF_PAGE_BUFFER1) ||
|
||||
(BufferNum == XISF_PAGE_BUFFER2)) {
|
||||
if ((InstancePtr->DeviceCode == XISF_ATMEL_DEV_AT45DB011D) &&
|
||||
(BufferNum != XISF_PAGE_BUFFER1)) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
} else {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
if (ReadPtr == NULL) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
if (ByteOffset > InstancePtr->BytesPerPage){
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
if ((NumBytes <= 0) || (NumBytes > InstancePtr->BytesPerPage)) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
if (BufferNum == XISF_PAGE_BUFFER1) {
|
||||
/*
|
||||
* Buffer 1 Fast Read.
|
||||
*/
|
||||
ReadPtr[BYTE1] = XISF_CMD_FAST_BUF1_READ;
|
||||
} else {
|
||||
/*
|
||||
* Buffer 2 Fast Read.
|
||||
*/
|
||||
ReadPtr[BYTE1] = XISF_CMD_FAST_BUF2_READ;
|
||||
}
|
||||
|
||||
ReadPtr[BYTE2] = (u8) (0x00);
|
||||
ReadPtr[BYTE3] = (u8) (ByteOffset >> XISF_ADDR_SHIFT8);
|
||||
ReadPtr[BYTE4] = (u8) ByteOffset;
|
||||
ReadPtr[BYTE5] = (u8) (XISF_DUMMYBYTE);
|
||||
|
||||
/*
|
||||
* Initiate the Transfer.
|
||||
*/
|
||||
Status = XIsf_Transfer(InstancePtr, ReadPtr, ReadPtr,
|
||||
NumBytes + XISF_CMD_FAST_READ_EXTRA_BYTES);
|
||||
if (Status != (int)(XST_SUCCESS)) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function reads the data from OTP area of the Serial Flash.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param Address is the starting address in OTP area of the Serial Flash
|
||||
* from which the data is to be read.
|
||||
* @param ReadPtr is a pointer to the memory where the data read from the
|
||||
* Serial Flash is stored.
|
||||
* @param ByteCount is the number of bytes to be read from the Serial
|
||||
* Flash.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
* - This operation is only supported for Intel Serial Flash.
|
||||
* - Minimum of one byte and a maximum of an entire Serial Flash
|
||||
* array can be read.
|
||||
******************************************************************************/
|
||||
static int ReadOTPData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr,
|
||||
u32 ByteCount)
|
||||
{
|
||||
int Status = (int)(XST_FAILURE);
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
Xil_AssertNonvoid(Address != 0);
|
||||
Xil_AssertNonvoid(ReadPtr != NULL);
|
||||
Xil_AssertNonvoid(ByteCount != 0);
|
||||
|
||||
#if (XPAR_XISF_FLASH_FAMILY == INTEL)
|
||||
if (ByteCount <= 0 ) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
if (ReadPtr == NULL) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
ReadPtr[BYTE1] = XISF_CMD_OTP_READ;
|
||||
ReadPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16);
|
||||
ReadPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8);
|
||||
ReadPtr[BYTE4] = (u8) Address;
|
||||
ReadPtr[BYTE5] = (u8) (XISF_DUMMYBYTE);
|
||||
|
||||
|
||||
/*
|
||||
* Initiate the Transfer.
|
||||
*/
|
||||
Status = XIsf_Transfer(InstancePtr, ReadPtr, ReadPtr,
|
||||
ByteCount + XISF_OTP_RDWR_EXTRA_BYTES);
|
||||
if (Status != (int)(XST_SUCCESS)) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
#endif /* (XPAR_XISF_FLASH_FAMILY == INTEL) */
|
||||
|
||||
return Status;
|
||||
}
|
411
lib/sw_services/xilisf/src/xilisf_spr.c
Normal file
411
lib/sw_services/xilisf/src/xilisf_spr.c
Normal file
|
@ -0,0 +1,411 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 - 2015 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
|
||||
* XILINX 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 xilisf_spr.c
|
||||
*
|
||||
* This file contains the library functions to operate on Sector Protection
|
||||
* feature of the Serial Flash. Refer xilisf.h for a detailed description.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ------- -------- -----------------------------------------------
|
||||
* 1.00a ksu/sdm 03/03/08 First release
|
||||
* 2.01a sdm 01/04/10 Added Support for Winbond W25QXX/W25XX devices
|
||||
* 2.04a sdm 08/17/10 Updated to support Numonyx (N25QXX) and Spansion
|
||||
* flash memories
|
||||
* 5.0 sb 08/05/14 Added Call back to lib interrupt handler
|
||||
* after XIsf_Transfer Calls.
|
||||
* Changed API:
|
||||
* - XIsf_SectorProtect()
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "include/xilisf.h"
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
extern int XIsf_Transfer(XIsf *InstancePtr, u8 *WritePtr, u8* ReadPtr,
|
||||
u32 ByteCount);
|
||||
extern int XIsf_GetStatus(XIsf *InstancePtr, u8 *ReadPtr);
|
||||
static int SprRead(XIsf *InstancePtr, u8 *ReadPtr);
|
||||
static int SprProgram(XIsf *InstancePtr, u8 *BufferPtr);
|
||||
|
||||
static int SprErase(XIsf *InstancePtr);
|
||||
static int SpEnable(XIsf *InstancePtr);
|
||||
static int SpDisable(XIsf *InstancePtr);
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
extern u32 XIsf_StatusEventInfo;
|
||||
extern unsigned int XIsf_ByteCountInfo;
|
||||
/************************** Function Definitions ******************************/
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This API is used for performing Sector Protect related operations.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param Operation is the type of Sector Protect operation to be
|
||||
* performed on the Serial Flash.
|
||||
* The different operations are
|
||||
* - XISF_SPR_READ: Read Sector Protection Register
|
||||
* - XISF_SPR_WRITE: Write Sector Protection Register
|
||||
* - XISF_SPR_ERASE: Erase Sector Protection Register
|
||||
* - XISF_SP_ENABLE: Enable Sector Protection
|
||||
* - XISF_SP_DISABLE: Disable Sector Protection
|
||||
* @param BufferPtr is a pointer to the memory where the SPR content is
|
||||
* read to/written from. This argument can be NULL if the
|
||||
* Operation is SprErase, SpEnable and SpDisable.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
* - The SPR content is stored at the fourth location pointed
|
||||
* by the BufferPtr when performing XISF_SPR_READ operation.
|
||||
* - For Intel, STM, Winbond and Spansion Serial Flash, the user
|
||||
* application must call the XIsf_WriteEnable() API by passing
|
||||
* XISF_WRITE_ENABLE as an argument, before calling the
|
||||
* XIsf_SectorProtect() API, for Sector Protect Register Write
|
||||
* (XISF_SPR_WRITE) operation.
|
||||
* - Atmel Flash supports all these Sector Protect operations.
|
||||
* - Intel, STM, Winbond and Spansion Flash support only Sector
|
||||
* Protect Read and Sector Protect Write operations.
|
||||
*
|
||||
******************************************************************************/
|
||||
int XIsf_SectorProtect(XIsf *InstancePtr, XIsf_SpOperation Operation,
|
||||
u8 *BufferPtr)
|
||||
{
|
||||
int Status = (int)(XST_FAILURE);
|
||||
u8 Mode;
|
||||
|
||||
switch (Operation) {
|
||||
case XISF_SPR_READ:
|
||||
Status = SprRead(InstancePtr, BufferPtr);
|
||||
break;
|
||||
|
||||
case XISF_SPR_WRITE:
|
||||
Status = SprProgram(InstancePtr, BufferPtr);
|
||||
break;
|
||||
|
||||
case XISF_SPR_ERASE:
|
||||
Status = SprErase(InstancePtr);
|
||||
break;
|
||||
|
||||
case XISF_SP_ENABLE:
|
||||
Status = SpEnable(InstancePtr);
|
||||
break;
|
||||
|
||||
case XISF_SP_DISABLE:
|
||||
Status = SpDisable(InstancePtr);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Added Comment for MISRA C */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the Transfer Mode
|
||||
*/
|
||||
Mode = XIsf_GetTransferMode(InstancePtr);
|
||||
|
||||
if(Mode == XISF_INTERRUPT_MODE){
|
||||
InstancePtr->StatusHandler(InstancePtr,
|
||||
XIsf_StatusEventInfo, XIsf_ByteCountInfo);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function reads the content of the Sector Protection Register(SPR).
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param ReadPtr is a pointer to the memory where the SPR content is
|
||||
* copied.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
* - This operation is supported for Atmel, Intel, STM, Winbond
|
||||
* and Spansion Serial Flash.
|
||||
* - The SPR content is stored at the fourth location pointed
|
||||
* by the ReadPtr for Atmel Serial Flash and at second location
|
||||
* for STM/Intel/Winbond/Spansion Serial Flash.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int SprRead(XIsf *InstancePtr, u8 *ReadPtr)
|
||||
{
|
||||
int Status;
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
|
||||
|
||||
if (ReadPtr == NULL) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
|
||||
u32 Index;
|
||||
|
||||
/*
|
||||
* Prepare the Write Buffer.
|
||||
*/
|
||||
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SPR_READ;
|
||||
|
||||
for(Index = 1; Index < (InstancePtr->NumOfSectors +
|
||||
XISF_CMD_SEND_EXTRA_BYTES); Index++) {
|
||||
InstancePtr->WriteBufPtr[Index] = XISF_DUMMYBYTE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initiate the Transfer.
|
||||
*/
|
||||
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, ReadPtr,
|
||||
InstancePtr->NumOfSectors +
|
||||
XISF_CMD_SEND_EXTRA_BYTES);
|
||||
|
||||
#else
|
||||
|
||||
Status = XIsf_GetStatus(InstancePtr, ReadPtr);
|
||||
|
||||
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
|
||||
|
||||
if (Status != (int)(XST_SUCCESS)) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
return (int)(XST_SUCCESS);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function writes to the Sector Protection Register(SPR).
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param BufferPtr is the pointer to the data to be written to SPR.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note This operation is supported for Atmel, Intel, STM, Winbond and
|
||||
* Spansion Serial Flash.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int SprProgram(XIsf *InstancePtr, u8 *BufferPtr)
|
||||
{
|
||||
int Status;
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
|
||||
if (BufferPtr == NULL) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
|
||||
u32 Index;
|
||||
|
||||
/*
|
||||
* Prepare the Write Buffer.
|
||||
*/
|
||||
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SPR_BYTE1;
|
||||
InstancePtr->WriteBufPtr[BYTE2] = XISF_CMD_SPR_BYTE2;
|
||||
InstancePtr->WriteBufPtr[BYTE3] = XISF_CMD_SPR_BYTE3;
|
||||
InstancePtr->WriteBufPtr[BYTE4] = XISF_CMD_SPR_BYTE4_PROGRAM;
|
||||
|
||||
for(Index = 4; Index < (InstancePtr->NumOfSectors +
|
||||
XISF_CMD_SEND_EXTRA_BYTES); Index++) {
|
||||
InstancePtr->WriteBufPtr[Index] = *BufferPtr++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initiate the Transfer.
|
||||
*/
|
||||
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
|
||||
InstancePtr->NumOfSectors +
|
||||
XISF_CMD_SEND_EXTRA_BYTES);
|
||||
#else
|
||||
|
||||
Status = XIsf_Write(InstancePtr, XISF_WRITE_STATUS_REG,
|
||||
(void*) BufferPtr);
|
||||
|
||||
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
|
||||
|
||||
if (Status != (int)(XST_SUCCESS)) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
|
||||
return (int)(XST_SUCCESS);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function erases the content of the Sector Protection Register(SPR).
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note This operation is only supported for Atmel Serial Flash.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int SprErase(XIsf *InstancePtr)
|
||||
{
|
||||
int Status = (int)(XST_FAILURE);
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
|
||||
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
|
||||
/*
|
||||
* Prepare the Write Buffer.
|
||||
*/
|
||||
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SPR_BYTE1;
|
||||
InstancePtr->WriteBufPtr[BYTE2] = XISF_CMD_SPR_BYTE2;
|
||||
InstancePtr->WriteBufPtr[BYTE3] = XISF_CMD_SPR_BYTE3;
|
||||
InstancePtr->WriteBufPtr[BYTE4] = XISF_CMD_SPR_BYTE4_ERASE;
|
||||
|
||||
/*
|
||||
* Initiate the Transfer.
|
||||
*/
|
||||
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
|
||||
XISF_CMD_SEND_EXTRA_BYTES);
|
||||
|
||||
if (Status != (int)(XST_SUCCESS)) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function enables Sector Protection. Sectors specified for protection in
|
||||
* the Sector Protection Register are protected by using this operation.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note This operation is only supported for Atmel Serial Flash.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int SpEnable(XIsf *InstancePtr)
|
||||
{
|
||||
int Status = (int)(XST_FAILURE);
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
|
||||
|
||||
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
|
||||
/*
|
||||
* Prepare the Write Buffer.
|
||||
*/
|
||||
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SPR_BYTE1;
|
||||
InstancePtr->WriteBufPtr[BYTE2] = XISF_CMD_SPR_BYTE2;
|
||||
InstancePtr->WriteBufPtr[BYTE3] = XISF_CMD_SPR_BYTE3;
|
||||
InstancePtr->WriteBufPtr[BYTE4] = XISF_CMD_SPR_BYTE4_ENABLE;
|
||||
|
||||
/*
|
||||
* Initiate the Transfer.
|
||||
*/
|
||||
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
|
||||
XISF_CMD_SEND_EXTRA_BYTES);
|
||||
|
||||
if (Status != (int)(XST_SUCCESS)) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function Disables Sector Protection.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note This operation is only supported for Atmel Serial Flash.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int SpDisable(XIsf *InstancePtr)
|
||||
{
|
||||
int Status = (int)(XST_FAILURE);
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
|
||||
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
|
||||
/*
|
||||
* Prepare the Write Buffer.
|
||||
*/
|
||||
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SPR_BYTE1;
|
||||
InstancePtr->WriteBufPtr[BYTE2] = XISF_CMD_SPR_BYTE2;
|
||||
InstancePtr->WriteBufPtr[BYTE3] = XISF_CMD_SPR_BYTE3;
|
||||
InstancePtr->WriteBufPtr[BYTE4] = XISF_CMD_SPR_BYTE4_DISABLE;
|
||||
|
||||
/*
|
||||
* Initiate the Transfer.
|
||||
*/
|
||||
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
|
||||
XISF_CMD_SEND_EXTRA_BYTES);
|
||||
|
||||
if (Status != (int)(XST_SUCCESS)) {
|
||||
return (int)(XST_FAILURE);
|
||||
}
|
||||
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
|
||||
|
||||
return Status;
|
||||
}
|
975
lib/sw_services/xilisf/src/xilisf_write.c
Normal file
975
lib/sw_services/xilisf/src/xilisf_write.c
Normal file
|
@ -0,0 +1,975 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 - 2015 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
|
||||
* XILINX 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 xilisf_write.c
|
||||
*
|
||||
* This file contains the library functions to write to the Serial Flash
|
||||
* devices. Refer xilisf.h for detailed description.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ------- -------- -----------------------------------------------
|
||||
* 1.00a ksu/sdm 03/03/08 First release
|
||||
* 2.01a sdm 01/04/10 Added Support for Winbond W25QXX/W25XX devices
|
||||
* 2.04a sdm 08/17/10 Updated to support Numonyx (N25QXX) and Spansion
|
||||
* flash memories
|
||||
* 3.00a srt 06/20/12 Updated to support interfaces SPI PS and QSPI PS.
|
||||
* Added support to SST flash on SPI PS interface.
|
||||
* 5.0 sb 08/05/14 Updated support for > 128 MB flash for PSQSPI
|
||||
* interface.
|
||||
* Changed API:
|
||||
* WriteData()
|
||||
* XIsf_Write()
|
||||
* 5.2 asa 05/12/15 Added support for Micron (N25Q256A) flash part
|
||||
* which supports 4 byte addressing.
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "include/xilisf.h"
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
#define SIXTEENMB 0x1000000 /**< Sixteen MB */
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
extern int XIsf_Transfer(XIsf *InstancePtr, u8 *WritePtr, u8* ReadPtr,
|
||||
u32 ByteCount);
|
||||
extern u32 GetRealAddr(XIsf_Iface *QspiPtr, u32 Address);
|
||||
|
||||
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
||||
extern int SendBankSelect(XIsf *InstancePtr, u32 BankSel);
|
||||
#endif
|
||||
static int WriteData(XIsf *InstancePtr, u8 Command, u32 Address,
|
||||
const u8 *BufferPtr, u32 ByteCount);
|
||||
static int AutoPageWrite(XIsf *InstancePtr, u32 Address);
|
||||
static int BufferWrite(XIsf *InstancePtr, u8 BufferNum, const u8 *WritePtr,
|
||||
u32 ByteOffset, u32 NumBytes);
|
||||
static int BufferToFlashWriteWithErase(XIsf *InstancePtr, u8 BufferNum,
|
||||
u32 Address);
|
||||
static int BufferToFlashWriteWithoutErase(XIsf *InstancePtr, u8 BufferNum,
|
||||
u32 Address);
|
||||
static int WriteSR(XIsf *InstancePtr, u8 SRData);
|
||||
static int WriteSR2(XIsf *InstancePtr, u8 *SRData);
|
||||
static int WriteOTPData(XIsf *InstancePtr, u32 Address, const u8 *BufferPtr);
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
extern u32 XIsf_StatusEventInfo;
|
||||
extern unsigned int XIsf_ByteCountInfo;
|
||||
/************************** Function Definitions ******************************/
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This API writes the data to the Serial Flash.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param Operation is the type of write operation to be performed on the
|
||||
* Serial Flash.
|
||||
* The different operations are
|
||||
* - XISF_WRITE: Normal Write
|
||||
* - XISF_DUAL_IP_PAGE_WRITE: Dual Input Fast Program
|
||||
* - XISF_DUAL_IP_EXT_PAGE_WRITE: Dual Input Extended Fast Program
|
||||
* - XISF_QUAD_IP_PAGE_WRITE: Quad Input Fast Program
|
||||
* - XISF_QUAD_IP_EXT_PAGE_WRITE: Quad Input Extended Fast Program
|
||||
* - XISF_AUTO_PAGE_WRITE: Auto Page Write
|
||||
* - XISF_BUFFER_WRITE: Buffer Write
|
||||
* - XISF_BUF_TO_PAGE_WRITE_WITH_ERASE: Buffer to Page Transfer
|
||||
* with Erase
|
||||
* - XISF_BUF_TO_PAGE_WRITE_WITHOUT_ERASE: Buffer to Page Transfer
|
||||
* without Erase
|
||||
* - XISF_WRITE_STATUS_REG: Status Register Write
|
||||
* - XISF_WRITE_STATUS_REG2: 2 byte Status Register Write
|
||||
* - XISF_OTP_WRITE: OTP Write.
|
||||
*
|
||||
* @param OpParamPtr is pointer to a structure variable which contains
|
||||
* operational parameters of the specified operation.
|
||||
* This parameter type is dependant on value of first argument
|
||||
* (Operation).
|
||||
*
|
||||
* - Normal Write (XISF_WRITE), Dual Input Fast Program
|
||||
* (XISF_DUAL_IP_PAGE_WRITE), Dual Input Extended Fast Program
|
||||
* (XISF_DUAL_IP_EXT_PAGE_WRITE), Quad Input Fast Program
|
||||
* (XISF_QUAD_IP_PAGE_WRITE), Quad Input Extended Fast Program
|
||||
* (XISF_QUAD_IP_EXT_PAGE_WRITE):
|
||||
* The OpParamPtr must be of type struct XIsf_WriteParam.
|
||||
* OpParamPtr->Address is the start address in the Serial Flash.
|
||||
* OpParamPtr->WritePtr is a pointer to the data to be written to
|
||||
* the Serial Flash.
|
||||
* OpParamPtr->NumBytes is the number of bytes to be written to
|
||||
* Serial Flash.
|
||||
* This operation is supported for Atmel, Intel, STM, Winbond and
|
||||
* Spansion Serial Flash.
|
||||
*
|
||||
* - Auto Page Write (XISF_AUTO_PAGE_WRITE):
|
||||
* The OpParamPtr must be of 32 bit unsigned integer variable.
|
||||
* This is the address of page number in the Serial Flash which is
|
||||
* to be refreshed.
|
||||
* This operation is only supported for Atmel Serial Flash.
|
||||
*
|
||||
* - Buffer Write (XISF_BUFFER_WRITE):
|
||||
* The OpParamPtr must be of type struct
|
||||
* XIsf_BufferToFlashWriteParam.
|
||||
* OpParamPtr->BufferNum specifies the internal SRAM Buffer of the
|
||||
* Serial Flash. The valid values are XISF_PAGE_BUFFER1 or
|
||||
* XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case of
|
||||
* AT45DB011D Flash as it contains a single buffer.
|
||||
* OpParamPtr->WritePtr is a pointer to the data to be written to
|
||||
* the Serial Flash SRAM Buffer.
|
||||
* OpParamPtr->ByteOffset is byte offset in the buffer from where
|
||||
* the data is to be written.
|
||||
* OpParamPtr->NumBytes is number of bytes to be written to the
|
||||
* Buffer.
|
||||
* This operation is supported only for Atmel Serial Flash.
|
||||
*
|
||||
* - Buffer To Memory Write With Erase
|
||||
* (XISF_BUF_TO_PAGE_WRITE_WITH_ERASE)/
|
||||
* Buffer To Memory Write Without Erase
|
||||
* (XISF_BUF_TO_PAGE_WRITE_WITHOUT_ERASE):
|
||||
* The OpParamPtr must be of type struct
|
||||
* XIsf_BufferToFlashWriteParam.
|
||||
* OpParamPtr->BufferNum specifies the internal SRAM Buffer of the
|
||||
* Serial Flash. The valid values are XISF_PAGE_BUFFER1 or
|
||||
* XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case of
|
||||
* AT45DB011D Flash as it contains a single buffer.
|
||||
* OpParamPtr->Address is starting address in the Serial Flash
|
||||
* memory from where the data is to be written.
|
||||
* These operations are only supported for Atmel Serial Flash.
|
||||
*
|
||||
* - Write Status Register (XISF_WRITE_STATUS_REG):
|
||||
* The OpParamPtr must be of type of 8 bit unsigned integer
|
||||
* variable. This is the value to be written to the Status
|
||||
* Register.
|
||||
* This operation is only supported for Intel, STM Winbond and
|
||||
* Spansion Serial Flash.
|
||||
*
|
||||
* - Write Status Register2 (XISF_WRITE_STATUS_REG2):
|
||||
* The OpParamPtr must be of type (u8 *) and should point to two
|
||||
* 8 bit unsigned integer values. This is the value to be written
|
||||
* to the 16 bit Status Register.
|
||||
* This operation is only supported in Winbond (W25Q) Serial Flash.
|
||||
*
|
||||
* - One Time Programmable Area Write (XISF_OTP_WRITE):
|
||||
* The OpParamPtr must be of type struct XIsf_WriteParam.
|
||||
* OpParamPtr->Address is the address in the SRAM Buffer of the
|
||||
* Serial Flash to which the data is to be written.
|
||||
* OpParamPtr->WritePtr is a pointer to the data to be written to
|
||||
* the Serial Flash.
|
||||
* OpParamPtr->NumBytes should be set to 1 when performing
|
||||
* OTPWrite operation.
|
||||
* This operation is only supported for Intel Serial Flash.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
* - Application must fill the structure elements of the third
|
||||
* argument and pass its pointer by type casting it with void
|
||||
* pointer.
|
||||
* - For Intel, STM, Winbond and Spansion Serial Flash, the user
|
||||
* application must call the XIsf_WriteEnable() API by passing
|
||||
* XISF_WRITE_ENABLE as an argument, before calling the
|
||||
* XIsf_Write() API.
|
||||
*
|
||||
******************************************************************************/
|
||||
int XIsf_Write(XIsf *InstancePtr, XIsf_WriteOperation Operation,
|
||||
void *OpParamPtr)
|
||||
{
|
||||
int Status = (int)XST_FAILURE;
|
||||
u8 Mode;
|
||||
XIsf_WriteParam *WriteParamPtr;
|
||||
XIsf_BufferWriteParam *BufferWriteParamPtr;
|
||||
XIsf_BufferToFlashWriteParam *BufferToFlashWriteParamPtr;
|
||||
|
||||
if (InstancePtr == NULL) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
|
||||
if (InstancePtr->IsReady != TRUE) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
|
||||
if (NULL == OpParamPtr) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
|
||||
switch (Operation) {
|
||||
case XISF_WRITE:
|
||||
WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr;
|
||||
Xil_AssertNonvoid(WriteParamPtr != NULL);
|
||||
Status = WriteData(InstancePtr,
|
||||
XISF_CMD_PAGEPROG_WRITE,
|
||||
WriteParamPtr->Address,
|
||||
WriteParamPtr->WritePtr,
|
||||
WriteParamPtr->NumBytes);
|
||||
break;
|
||||
|
||||
case XISF_AUTO_PAGE_WRITE:
|
||||
Status = AutoPageWrite(InstancePtr,
|
||||
*((u32*)(void *) OpParamPtr));
|
||||
break;
|
||||
|
||||
case XISF_BUFFER_WRITE:
|
||||
BufferWriteParamPtr = (XIsf_BufferWriteParam*)
|
||||
(void *) OpParamPtr;
|
||||
Xil_AssertNonvoid(BufferWriteParamPtr != NULL);
|
||||
Status = BufferWrite(InstancePtr,
|
||||
BufferWriteParamPtr->BufferNum,
|
||||
BufferWriteParamPtr->WritePtr,
|
||||
BufferWriteParamPtr->ByteOffset,
|
||||
BufferWriteParamPtr->NumBytes);
|
||||
break;
|
||||
|
||||
case XISF_BUF_TO_PAGE_WRITE_WITH_ERASE:
|
||||
BufferToFlashWriteParamPtr =
|
||||
(XIsf_BufferToFlashWriteParam*)(void *) OpParamPtr;
|
||||
Xil_AssertNonvoid(BufferToFlashWriteParamPtr != NULL);
|
||||
Status = BufferToFlashWriteWithErase(InstancePtr,
|
||||
BufferToFlashWriteParamPtr->BufferNum,
|
||||
BufferToFlashWriteParamPtr->Address);
|
||||
break;
|
||||
|
||||
case XISF_BUF_TO_PAGE_WRITE_WITHOUT_ERASE:
|
||||
BufferToFlashWriteParamPtr =
|
||||
(XIsf_BufferToFlashWriteParam*)(void *) OpParamPtr;
|
||||
Xil_AssertNonvoid(BufferToFlashWriteParamPtr != NULL);
|
||||
Status = BufferToFlashWriteWithoutErase(InstancePtr,
|
||||
BufferToFlashWriteParamPtr->BufferNum,
|
||||
BufferToFlashWriteParamPtr->Address);
|
||||
break;
|
||||
|
||||
case XISF_WRITE_STATUS_REG:
|
||||
Status = WriteSR(InstancePtr,
|
||||
*((u8*)(void *) OpParamPtr));
|
||||
break;
|
||||
|
||||
case XISF_OTP_WRITE:
|
||||
WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr;
|
||||
Xil_AssertNonvoid(WriteParamPtr != NULL);
|
||||
if (1 == WriteParamPtr->NumBytes) {
|
||||
Status = WriteOTPData(InstancePtr,
|
||||
WriteParamPtr->Address,
|
||||
WriteParamPtr->WritePtr);
|
||||
}
|
||||
break;
|
||||
|
||||
case XISF_WRITE_STATUS_REG2:
|
||||
Status = WriteSR2(InstancePtr,
|
||||
(u8*)(void *) OpParamPtr);
|
||||
break;
|
||||
|
||||
#if ((XPAR_XISF_FLASH_FAMILY == WINBOND) || (XPAR_XISF_FLASH_FAMILY == STM) \
|
||||
|| (XPAR_XISF_FLASH_FAMILY == SPANSION))
|
||||
case XISF_QUAD_IP_PAGE_WRITE:
|
||||
WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr;
|
||||
Xil_AssertNonvoid(WriteParamPtr != NULL);
|
||||
Status = WriteData(InstancePtr,
|
||||
XISF_CMD_QUAD_IP_PAGE_WRITE,
|
||||
WriteParamPtr->Address,
|
||||
WriteParamPtr->WritePtr,
|
||||
WriteParamPtr->NumBytes);
|
||||
break;
|
||||
|
||||
#endif /*((XPAR_XISF_FLASH_FAMILY == WINBOND) ||
|
||||
(XPAR_XISF_FLASH_FAMILY == STM) ||
|
||||
(XPAR_XISF_FLASH_FAMILY == SPANSION))*/
|
||||
|
||||
#if (XPAR_XISF_FLASH_FAMILY == STM)
|
||||
case XISF_DUAL_IP_PAGE_WRITE:
|
||||
WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr;
|
||||
Xil_AssertNonvoid(WriteParamPtr != NULL);
|
||||
Status = WriteData(InstancePtr,
|
||||
XISF_CMD_DUAL_IP_PAGE_WRITE,
|
||||
WriteParamPtr->Address,
|
||||
WriteParamPtr->WritePtr,
|
||||
WriteParamPtr->NumBytes);
|
||||
break;
|
||||
|
||||
case XISF_DUAL_IP_EXT_PAGE_WRITE:
|
||||
WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr;
|
||||
Xil_AssertNonvoid(WriteParamPtr != NULL);
|
||||
Status = WriteData(InstancePtr,
|
||||
XISF_CMD_DUAL_IP_EXT_PAGE_WRITE,
|
||||
WriteParamPtr->Address,
|
||||
WriteParamPtr->WritePtr,
|
||||
WriteParamPtr->NumBytes);
|
||||
break;
|
||||
|
||||
case XISF_QUAD_IP_EXT_PAGE_WRITE:
|
||||
WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr;
|
||||
Xil_AssertNonvoid(WriteParamPtr != NULL);
|
||||
Status = WriteData(InstancePtr,
|
||||
XISF_CMD_QUAD_IP_EXT_PAGE_WRITE,
|
||||
WriteParamPtr->Address,
|
||||
WriteParamPtr->WritePtr,
|
||||
WriteParamPtr->NumBytes);
|
||||
break;
|
||||
#endif /* (XPAR_XISF_FLASH_FAMILY == STM) */
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Mode = XIsf_GetTransferMode(InstancePtr);
|
||||
|
||||
if(Mode == XISF_INTERRUPT_MODE){
|
||||
InstancePtr->StatusHandler(InstancePtr,
|
||||
XIsf_StatusEventInfo, XIsf_ByteCountInfo);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function writes the data to the specified address locations in Serial
|
||||
* Flash.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param Address is the address in the Serial Flash memory, where the
|
||||
* data is to be written.
|
||||
* @param BufferPtr is a pointer to the data to be written to Serial
|
||||
* Flash.
|
||||
* @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 function.
|
||||
* - This operation is supported for Atmel, Intel, STM, Winbond
|
||||
* and Spansion Serial Flash.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int WriteData(XIsf *InstancePtr, u8 Command, u32 Address,
|
||||
const u8 *BufferPtr, u32 ByteCount)
|
||||
{
|
||||
u8 Mode;
|
||||
u32 Index;
|
||||
u32 BankSel;
|
||||
u32 RealAddr;
|
||||
int Status;
|
||||
u8 FlagStatus[2] = {0};
|
||||
u8 FlashStatus[2] = {0};
|
||||
u8 * NULLPtr = NULL;
|
||||
const u8 * LocalBufPtr = BufferPtr;
|
||||
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
||||
u32 FlashMake = InstancePtr->ManufacturerID;
|
||||
#endif
|
||||
u8 ReadStatusCmdBuf[] = { READ_STATUS_CMD, 0 };
|
||||
u8 ReadFlagSRCmd[] = {READ_FLAG_STATUS_CMD, 0};
|
||||
|
||||
if ((ByteCount <= 0) || (ByteCount > InstancePtr->BytesPerPage)) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
|
||||
if (LocalBufPtr == NULL) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate address based on type of connection
|
||||
* If stacked assert the slave select based on address
|
||||
*/
|
||||
RealAddr = GetRealAddr(InstancePtr->SpiInstPtr, Address);
|
||||
|
||||
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
||||
/*
|
||||
* 0x18 is the DeviceIDMemSize for different make of
|
||||
* flashes of size 16MB
|
||||
*/
|
||||
if(InstancePtr->DeviceIDMemSize > 0x18) {
|
||||
|
||||
/*
|
||||
* Get the Transfer Mode
|
||||
*/
|
||||
Mode = XIsf_GetTransferMode(InstancePtr);
|
||||
|
||||
/*
|
||||
* Seting the transfer mode to Polled Mode before
|
||||
* performing the Bank Select operation.
|
||||
*/
|
||||
XIsf_SetTransferMode(InstancePtr, XISF_POLLING_MODE);
|
||||
|
||||
/*
|
||||
* Calculate bank
|
||||
*/
|
||||
BankSel = RealAddr/SIXTEENMB;
|
||||
/*
|
||||
* Select bank
|
||||
*/
|
||||
(void)SendBankSelect(InstancePtr, BankSel);
|
||||
|
||||
/*
|
||||
* Restoring the transfer mode back
|
||||
*/
|
||||
XIsf_SetTransferMode(InstancePtr, Mode);
|
||||
}
|
||||
#endif
|
||||
#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \
|
||||
(!defined(XPAR_XISF_INTERFACE_PSQSPI)))
|
||||
if (InstancePtr->FourByteAddrMode == TRUE) {
|
||||
InstancePtr->WriteBufPtr[BYTE1] = Command;
|
||||
InstancePtr->WriteBufPtr[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT24);
|
||||
InstancePtr->WriteBufPtr[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT16);
|
||||
InstancePtr->WriteBufPtr[BYTE4] = (u8) (RealAddr >> XISF_ADDR_SHIFT8);
|
||||
InstancePtr->WriteBufPtr[BYTE5] = (u8) (RealAddr);
|
||||
for(Index = 5U; Index < (ByteCount + XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE);
|
||||
Index++) {
|
||||
InstancePtr->WriteBufPtr[Index] = *LocalBufPtr;
|
||||
LocalBufPtr += 1;
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
InstancePtr->WriteBufPtr[BYTE1] = Command;
|
||||
InstancePtr->WriteBufPtr[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT16);
|
||||
InstancePtr->WriteBufPtr[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT8);
|
||||
InstancePtr->WriteBufPtr[BYTE4] = (u8) (RealAddr);
|
||||
for(Index = 4U; Index < (ByteCount + XISF_CMD_SEND_EXTRA_BYTES);
|
||||
Index++) {
|
||||
InstancePtr->WriteBufPtr[Index] = *LocalBufPtr;
|
||||
LocalBufPtr += 1;
|
||||
}
|
||||
#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \
|
||||
(!defined(XPAR_XISF_INTERFACE_PSQSPI)))
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
||||
/*
|
||||
* Enable write before transfer
|
||||
*/
|
||||
Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE);
|
||||
#endif
|
||||
if (InstancePtr->FourByteAddrMode == TRUE) {
|
||||
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr,
|
||||
(ByteCount + XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE));
|
||||
} else {
|
||||
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr,
|
||||
(ByteCount + XISF_CMD_SEND_EXTRA_BYTES));
|
||||
}
|
||||
if (Status != (int)XST_SUCCESS) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
||||
if((InstancePtr->NumDie > 1) &&
|
||||
(FlashMake == XISF_MANUFACTURER_ID_MICRON)) {
|
||||
Status = XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus,
|
||||
(u32)sizeof(ReadFlagSRCmd));
|
||||
if(Status != (int)XST_SUCCESS){
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for the write command to the Flash to be completed, it takes
|
||||
* some time for the data to be written
|
||||
*/
|
||||
while (1) {
|
||||
/*
|
||||
* Poll the status register of the Flash to determine when it
|
||||
* completes, by sending a read status command and receiving
|
||||
* status byte
|
||||
*/
|
||||
Status = XIsf_Transfer(InstancePtr, ReadStatusCmdBuf,
|
||||
FlashStatus, (u32)sizeof(ReadStatusCmdBuf));
|
||||
if(Status != (int)XST_SUCCESS){
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* If status indicates the write is done, then 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 ((FlashStatus[1] & 0x01) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if((InstancePtr->NumDie > 1) &&
|
||||
(FlashMake == XISF_MANUFACTURER_ID_MICRON)) {
|
||||
Status = XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus,
|
||||
(u32)sizeof(ReadFlagSRCmd));
|
||||
if(Status != (int)XST_SUCCESS){
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function Auto rewrites the contents of a Page in the Serial Flash.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param Address is the address of the page to be refreshed.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note This operation is only supported for Atmel Serial Flash.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int AutoPageWrite(XIsf *InstancePtr, u32 Address)
|
||||
{
|
||||
int Status = (int)XST_FAILURE;
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
Xil_AssertNonvoid(Address != 0);
|
||||
|
||||
|
||||
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
|
||||
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_AUTOPAGE_WRITE;
|
||||
InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16);
|
||||
InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8);
|
||||
InstancePtr->WriteBufPtr[BYTE4] = (XISF_DUMMYBYTE);
|
||||
|
||||
/*
|
||||
* Initiate the Transfer.
|
||||
*/
|
||||
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
|
||||
XISF_CMD_SEND_EXTRA_BYTES);
|
||||
if (Status != (int)XST_SUCCESS) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function writes data to the specified SRAM buffer of the Serial Flash.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param BufferNum specifies the internal SRAM Buffer of the Serial
|
||||
* Flash. The valid values are XISF_PAGE_BUFFER1 or
|
||||
* XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case of
|
||||
* Atmel AT45DB011D Serial Flash as it contains a single buffer.
|
||||
* @param WritePtr is the pointer to the data to be written to the
|
||||
* Serial Flash SRAM Buffer.
|
||||
* @param ByteOffset is the byte offset in the buffer from where the
|
||||
* data is to be written.
|
||||
* @param NumBytes is the number of bytes to be written to the Buffer.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
* - A minimum of one byte and a maximum of one SRAM buffer can be
|
||||
* written using this function.
|
||||
* - This operation is only supported for Atmel Serial Flash.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int BufferWrite(XIsf *InstancePtr, u8 BufferNum, const u8 *WritePtr,
|
||||
u32 ByteOffset, u32 NumBytes)
|
||||
{
|
||||
int Status = (int)XST_FAILURE;
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
Xil_AssertNonvoid(BufferNum != 0);
|
||||
Xil_AssertNonvoid(WritePtr != NULL);
|
||||
Xil_AssertNonvoid(ByteOffset != 0);
|
||||
Xil_AssertNonvoid(NumBytes != 0);
|
||||
|
||||
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
|
||||
u16 Index;
|
||||
|
||||
/*
|
||||
* Check buffer number is valid or not.
|
||||
*/
|
||||
if ((BufferNum == XISF_PAGE_BUFFER1) ||
|
||||
(BufferNum == XISF_PAGE_BUFFER2)) {
|
||||
if ((InstancePtr->DeviceCode == XISF_ATMEL_DEV_AT45DB011D) &&
|
||||
(BufferNum != XISF_PAGE_BUFFER1)) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
}
|
||||
else{
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
|
||||
if (WritePtr == NULL) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
|
||||
if (ByteOffset > InstancePtr->BytesPerPage) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
|
||||
if ((NumBytes <= 0) || (NumBytes > InstancePtr->BytesPerPage)) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
if (BufferNum == XISF_PAGE_BUFFER1) {
|
||||
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BUFFER1_WRITE;
|
||||
}
|
||||
else{
|
||||
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BUFFER2_WRITE;
|
||||
}
|
||||
InstancePtr->WriteBufPtr[BYTE2] = (u8) (0x00);
|
||||
InstancePtr->WriteBufPtr[BYTE3] = (u8) (ByteOffset >> XISF_ADDR_SHIFT8);
|
||||
InstancePtr->WriteBufPtr[BYTE4] = (u8) ByteOffset;
|
||||
|
||||
|
||||
for(Index = 4; Index < NumBytes + XISF_CMD_SEND_EXTRA_BYTES; Index++) {
|
||||
InstancePtr->WriteBufPtr[Index] = *WritePtr++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initiate the Transfer.
|
||||
*/
|
||||
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
|
||||
(NumBytes + XISF_CMD_SEND_EXTRA_BYTES));
|
||||
if (Status != (int)XST_SUCCESS) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function first erases a page and then writes data from the specified
|
||||
* internal SRAM buffer to the specified locations in the Serial Flash.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param BufferNum specifies the internal SRAM Buffer, from which the
|
||||
* data needs to be written to the Serial Flash. The valid values
|
||||
* are XISF_PAGE_BUFFER1 or XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2
|
||||
* is not valid in the case of Atmel AT45DB011D Serial Flash as it
|
||||
* contains a single buffer.
|
||||
* @param Address is the starting address in the Serial Flash where
|
||||
* the data has to be written. Byte address in this address is
|
||||
* ignored as an entire Page is transferred using this API.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
* - A minimum of one Page and a maximum of one Page can be
|
||||
* written using this function.
|
||||
* - This operation is only supported for Atmel Serial Flash.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int BufferToFlashWriteWithErase(XIsf *InstancePtr, u8 BufferNum,
|
||||
u32 Address)
|
||||
{
|
||||
int Status = (int)XST_FAILURE;
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
Xil_AssertNonvoid(BufferNum != 0);
|
||||
Xil_AssertNonvoid(Address != 0);
|
||||
|
||||
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
|
||||
/*
|
||||
* Check whether the buffer number is valid or not.
|
||||
*/
|
||||
if ((BufferNum == XISF_PAGE_BUFFER1) ||
|
||||
(BufferNum == XISF_PAGE_BUFFER2)) {
|
||||
if ((InstancePtr->DeviceCode == XISF_ATMEL_DEV_AT45DB011D) &&
|
||||
(BufferNum != XISF_PAGE_BUFFER1)) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
|
||||
if (BufferNum == XISF_PAGE_BUFFER1) {
|
||||
/*
|
||||
* Buffer 1 to Page Program With Erase.
|
||||
*/
|
||||
InstancePtr->WriteBufPtr[BYTE1] =
|
||||
XISF_CMD_ERASE_BUF1TOPAGE_WRITE;
|
||||
} else {
|
||||
/*
|
||||
* Buffer 2 to Page Program With Erase.
|
||||
*/
|
||||
InstancePtr->WriteBufPtr[BYTE1] =
|
||||
XISF_CMD_ERASE_BUF2TOPAGE_WRITE;
|
||||
}
|
||||
InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16);
|
||||
InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8);
|
||||
InstancePtr->WriteBufPtr[BYTE4] = (u8) (XISF_DUMMYBYTE);
|
||||
|
||||
/*
|
||||
* Initiate the Transfer.
|
||||
*/
|
||||
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
|
||||
XISF_CMD_SEND_EXTRA_BYTES);
|
||||
if (Status != (int)XST_SUCCESS) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function writes data from the specified internal SRAM buffer to the
|
||||
* specified locations in the Serial Flash.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param BufferNum specifies the internal SRAM Buffer, from which the
|
||||
* data needs to be written to the Serial Flash. The valid values
|
||||
* are XISF_PAGE_BUFFER1 or XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2
|
||||
* is not valid in the case of Atmel AT45DB011D Serial Flash as it
|
||||
* contains a single buffer.
|
||||
* @param Address is the starting address in the Serial Flash where
|
||||
* data has to be written. Byte address in this address will be
|
||||
* ignored as an entire page of data is transferred using this
|
||||
* operation.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* - A minimum of one Page and a maximum of one Page can be
|
||||
* written using this function.
|
||||
* - This operation is only supported for Atmel Serial Flash.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int BufferToFlashWriteWithoutErase(XIsf *InstancePtr, u8 BufferNum,
|
||||
u32 Address)
|
||||
{
|
||||
int Status = (int)XST_FAILURE;
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
Xil_AssertNonvoid(BufferNum != 0);
|
||||
Xil_AssertNonvoid(Address != 0);
|
||||
|
||||
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
|
||||
/*
|
||||
* Check whether the buffer number is valid or not.
|
||||
*/
|
||||
if ((BufferNum == XISF_PAGE_BUFFER1) ||
|
||||
(BufferNum == XISF_PAGE_BUFFER2)) {
|
||||
if ((InstancePtr->DeviceCode == XISF_ATMEL_DEV_AT45DB011D) &&
|
||||
(XISF_PAGE_BUFFER1 != 1)) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
|
||||
if (BufferNum == XISF_PAGE_BUFFER1) {
|
||||
/*
|
||||
* Buffer 1 to Page Program Without Erase.
|
||||
*/
|
||||
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BUF1TOPAGE_WRITE;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Buffer 2 to Page Program Without Erase.
|
||||
*/
|
||||
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BUF2TOPAGE_WRITE;
|
||||
}
|
||||
|
||||
InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16);
|
||||
InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8);
|
||||
InstancePtr->WriteBufPtr[BYTE4] = (u8) (XISF_DUMMYBYTE);
|
||||
|
||||
/*
|
||||
* Initiate the Transfer.
|
||||
*/
|
||||
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
|
||||
XISF_CMD_SEND_EXTRA_BYTES);
|
||||
if (Status != (int)XST_SUCCESS) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function writes data to the Status Register of the Serial Flash.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param SRData is the value to be written to the Status Register
|
||||
* of the Serial Flash.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note This operation is only supported in Intel, STM, Winbond and
|
||||
* Spansion Serial Flash. This is the write of Status Register 1
|
||||
* for Winbond devices, write of Status Register 2 is handled by
|
||||
* WriteSR2.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int WriteSR(XIsf *InstancePtr, u8 SRData)
|
||||
{
|
||||
int Status = XST_FAILURE;
|
||||
|
||||
#if ((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) || \
|
||||
(XPAR_XISF_FLASH_FAMILY == WINBOND) || \
|
||||
(XPAR_XISF_FLASH_FAMILY == SPANSION) || (XPAR_XISF_FLASH_FAMILY == SST))
|
||||
/*
|
||||
* Prepare the Write Buffer.
|
||||
*/
|
||||
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_STATUSREG_WRITE;
|
||||
InstancePtr->WriteBufPtr[BYTE2] = SRData;
|
||||
|
||||
/*
|
||||
* Initiate the Transfer.
|
||||
*/
|
||||
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
|
||||
XISF_STATUS_RDWR_BYTES);
|
||||
if (Status != (int)XST_SUCCESS) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
#endif /* ((XPAR_XISF_FLASH_FAMILY==INTEL) || (XPAR_XISF_FLASH_FAMILY==STM) \\
|
||||
(XPAR_XISF_FLASH_FAMILY == WINBOND) ||
|
||||
(XPAR_XISF_FLASH_FAMILY == SPANSION)) */
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function writes data to Status Register of the Serial Flash. This API
|
||||
* should be used to write to the 16 bit status register in Winbond Quad Flash
|
||||
* (W25QXX).
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param SRData is of type (u8*) and points to the 16 bit value to be
|
||||
* written to the Status Register of the Serial Flash.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note This operation is only supported in Winbond (W25QXX) Serial
|
||||
* Flash.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int WriteSR2(XIsf *InstancePtr, u8 *SRData)
|
||||
{
|
||||
int Status = (int)XST_FAILURE;
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
Xil_AssertNonvoid(SRData != NULL);
|
||||
|
||||
#if (XPAR_XISF_FLASH_FAMILY == WINBOND)
|
||||
/*
|
||||
* Prepare the Write Buffer.
|
||||
*/
|
||||
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_STATUSREG_WRITE;
|
||||
InstancePtr->WriteBufPtr[BYTE2] = *SRData++;
|
||||
InstancePtr->WriteBufPtr[BYTE3] = *SRData;
|
||||
|
||||
/*
|
||||
* Initiate the Transfer.
|
||||
*/
|
||||
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
|
||||
XISF_STATUS_RDWR_BYTES + 1);
|
||||
if (Status != (int)XST_SUCCESS) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
#endif /* (XPAR_XISF_FLASH_FAMILY == WINBOND) */
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function writes one byte of data to the OTP area in the Serial Flash.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIsf instance.
|
||||
* @param Address is the address in the OTP area, where to write data.
|
||||
* @param BufferPtr is the pointer to the data to be written into OTP
|
||||
* region of Serial Flash.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note
|
||||
* - A minimum of one byte and a maximum of one byte can be
|
||||
* written using this function.
|
||||
* - This operation is supported only for Intel Serial Flash.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int WriteOTPData(XIsf *InstancePtr, u32 Address, const u8 *BufferPtr)
|
||||
{
|
||||
int Status = (int)XST_FAILURE;
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
Xil_AssertNonvoid(Address != 0);
|
||||
Xil_AssertNonvoid(BufferPtr != NULL);
|
||||
|
||||
|
||||
#if (XPAR_XISF_FLASH_FAMILY == INTEL)
|
||||
if (BufferPtr == NULL) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
|
||||
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_OTP_WRITE;
|
||||
InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16);
|
||||
InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8);
|
||||
InstancePtr->WriteBufPtr[BYTE4] = (u8) Address;
|
||||
InstancePtr->WriteBufPtr[BYTE5] = *BufferPtr;
|
||||
|
||||
/*
|
||||
* Initiate the Transfer.
|
||||
*/
|
||||
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
|
||||
XISF_OTP_RDWR_EXTRA_BYTES);
|
||||
if (Status != (int)XST_SUCCESS) {
|
||||
return (int)XST_FAILURE;
|
||||
}
|
||||
#endif /* (XPAR_XISF_FLASH_FAMILY == INTEL) */
|
||||
|
||||
return Status;
|
||||
}
|
Loading…
Add table
Reference in a new issue